diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index bcb1e93..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,418 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "discrete-logarithm" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40719d0398fbf7202e332c9caccc91d42a5da4e3f4bece86d823a75e0a73b34a" -dependencies = [ - "primal", - "rug", - "thiserror", -] - -[[package]] -name = "ec_crypto" -version = "0.1.0" -dependencies = [ - "discrete-logarithm", - "num", - "rand", - "rug", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gmp-mpfr-sys" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0205cd82059bc63b63cf516d714352a30c44f2c74da9961dfda2617ae6b5918" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "hamming" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" - -[[package]] -name = "libc" -version = "0.2.167" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "primal" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e5f354948532e6017fc91f9a5ff5ba1be0dabd3a0c9e9c417969cd4c1ad6e8" -dependencies = [ - "primal-check", - "primal-estimate", - "primal-sieve", -] - -[[package]] -name = "primal-bit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252429dbb8aeacc3233df500dc3a6a367bf28eb3a711272884d7540a7b636055" -dependencies = [ - "hamming", -] - -[[package]] -name = "primal-check" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" -dependencies = [ - "num-integer", -] - -[[package]] -name = "primal-estimate" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a432100a0b3a61085e75b5f89e9f42de73c0acb7dea5038b893697918105d822" - -[[package]] -name = "primal-sieve" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e982796d82203351983d3602a8d6372d1d7894e86960047ba0d4b7426a5edd3" -dependencies = [ - "primal-bit", - "primal-estimate", - "smallvec", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rug" -version = "1.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ae2c1089ec0575193eb9222881310cc1ed8bce3646ef8b81b44b518595b79d" -dependencies = [ - "az", - "gmp-mpfr-sys", - "libc", - "libm", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "syn" -version = "2.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 24e3edc..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ec_crypto" -version = "0.1.0" -edition = "2021" - -[dependencies] -rand = "0.8.5" -num = "0.4.3" -discrete-logarithm = "1.0.0" -rug = "1.26.1" diff --git a/keygen.py b/keygen.py new file mode 100644 index 0000000..641ebd8 --- /dev/null +++ b/keygen.py @@ -0,0 +1,93 @@ +from fractions import Fraction +import random +from dataclasses import dataclass +from sympy.ntheory.residue_ntheory import nthroot_mod +from itertools import cycle + +@dataclass +class ec: + a: int + b: int + p: int + + def ec_add(self, p1, p2): + if all(v1 == v2 for v1, v2 in zip(p1, p2)): + #print("H") + if self.p: + dy = Fraction((3*p1[0]**2 + self.a), 2*p1[1]) + else: + dy =(3*p1[0]**2 + self.a) / (2*p1[1]) + else: + if self.p: + dy = Fraction((p2[1] - p1[1]), (p2[0] - p1[0])) + else: + dy = (p2[1] - p1[1]) / (p2[0] - p1[0]) + res_x = dy ** 2 - p1[0] - p2[0] + res_y = (dy * (p1[0] - res_x) - p1[1]) + if self.p != None: + res_x = int(res_x % self.p) + res_y = int(res_y % self.p) + return (res_x, res_y) + return (float(res_x), float(res_y)) + def ec_mul(self, p, s): + for _ in range(s): + p = self.ec_add(p, p) + return p + def __getitem__(self, pos): + x = pos[0] + x_given = type(x) != slice + if x_given: value = x**3+self.a*x+self.b + else: raise ValueError() + solutions = [(x % self.p, s) for s in nthroot_mod(value, 2, self.p, True)] + return solutions + +@dataclass +class Person: + name: str + private: tuple[int, int] + public: tuple[int, int] + shared: tuple[int, int] + + def gen_keys(self, start, curve: ec): + self.private = random.randint(0, curve.p) + self.public = curve.ec_mul(start, self.private) + print(f"[{self.name}]: private: {self.private} -> public: {self.public[1]}") + return + + def gen_shared(self, public, curve: ec): + self.shared = curve.ec_mul(public, self.private) + return + + def diffie_hellman(curve: ec, alice, bob): + gen = (4, 10) + alice.gen_keys(gen, curve) + bob.gen_keys(gen, curve) + alice.gen_shared(bob.public, curve) + bob.gen_shared(alice.public, curve) + assert(alice.shared == bob.shared) + print(f"[{alice.name}|{bob.name}] generated equal shared keys") + + def xor(data, key): + key = str(key) + data = data.encode() if isinstance(data, str) else data + key = key.encode() if isinstance(key, str) else key + return bytearray(a ^ b for a, b in zip(data, cycle(key))) + + def send(self, msg, target): + encrypted = Person.xor(msg, self.shared[1]) + print(f"[{self.name}] sent message '{msg}' to {target.name}") + target.recv(encrypted, self) + + def recv(self, msg, source): + decrypted = str(Person.xor(msg, self.shared[1]), encoding='utf-8') + print(f"[{self.name}] received message '{decrypted}' from {source.name}") + + +if __name__ == "__main__": + curve = ec(0, 7, 1109) + alice = Person("alice", 0, 0, 0) + bob = Person("bob", 0, 0, 0) + + Person.diffie_hellman(curve, alice, bob) + alice.send("Hello world", bob) + diff --git a/src/keygen.rs b/src/keygen.rs deleted file mode 100644 index 11d26e6..0000000 --- a/src/keygen.rs +++ /dev/null @@ -1,132 +0,0 @@ -use core::str; -use std::u32; - -use num::{pow::Pow, Integer}; -use rand::{distributions::Standard, prelude::Distribution}; - -use crate::utils::*; - -struct EllipticCurve -where - BigInt: Integer, -{ - a: BigInt, - b: BigInt, - r#mod: BigInt, -} -impl EllipticCurve -where - BigInt: Integer + std::marker::Copy + Pow, - Standard: Distribution, -{ - pub fn new(a: BigInt, b: BigInt, r#mod: BigInt) -> Self { - EllipticCurve { a, b, r#mod } - } - - pub fn y(&self, x: BigInt) -> BigInt { - (x.pow(3) + self.b * x + self.a) % self.r#mod - } - pub fn random(&self) -> (BigInt, BigInt) { - let mut start = rand::random::() % self.r#mod; - let i_count = rand::random::(); - - for _ in 0..i_count { - start = self.y(start); - } - - (start, self.y(start)) - } -} - -pub struct Person { - pub name: String, - private_key: Option, - pub public_key: Option, - pub shared_key: Option, - pub gen: Option, - pub r#mod: Option, -} -impl Person { - pub fn new(name: &str) -> Self { - Person { - name: name.to_string(), - private_key: None, - public_key: None, - shared_key: None, - gen: None, - r#mod: None, - } - } - - pub fn gen_keys(&mut self, start: u32, r#mod: u32) { - let private = rand::random::() % r#mod; - self.private_key = Some(private.into()); - let public = mod_pow(start, private.into(), r#mod); - self.public_key = Some(public); - self.gen = Some(start); - self.r#mod = Some(r#mod); - eprintln!( - "[{}] private: {} -> public: {}", - self.name, - self.private_key.unwrap(), - self.public_key.unwrap() - ); - } - - pub fn gen_shared(&mut self, public: u32, r#mod: u32) { - self.shared_key = Some(mod_pow(public, self.private_key.unwrap(), r#mod)) - } - - pub fn diffie_hellman(p1: &mut Self, p2: &mut Self) { - let m: u32 = 1109; - let curve = EllipticCurve::new(0, 7, m); - let gen = curve.random().1; - - eprintln!( - "Start params: x³+{}x+{}, mod {}, generator {}", - 0, 7, m, gen - ); - - p1.gen_keys(gen, m.into()); - p2.gen_keys(gen, m.into()); - p1.gen_shared(p2.public_key.unwrap(), m.into()); - p2.gen_shared(p1.public_key.unwrap(), m.into()); - assert_eq!(p1.shared_key, p2.shared_key); - eprintln!( - "[{}] Shared key for {}: {}", - p1.name, - p2.name, - p1.shared_key.unwrap() - ); - } - - fn xor_cipher(msg: &[u8], key: u32) -> Vec { - let key_bytes = key.to_le_bytes(); - let key_len = key_bytes.len(); - - msg.iter() - .enumerate() - .map(|(i, &byte)| byte ^ key_bytes[i % key_len]) - .collect() - } - - pub fn send(&self, msg_raw: &[u8], target: &Self) { - let encrypted_raw = Self::xor_cipher(msg_raw, self.shared_key.unwrap()); - let encrypted = str::from_utf8(&encrypted_raw).unwrap_or("not displayable"); - let msg = str::from_utf8(&msg_raw).unwrap_or("not displayable"); - eprintln!( - "[{}] Sending message '{}' ({}) to {}", - self.name, msg, encrypted, target.name - ); - target.recv(&encrypted_raw, self); - } - fn recv(&self, msg_raw: &[u8], source: &Self) { - let decrypted_raw = Self::xor_cipher(msg_raw, self.shared_key.unwrap()); - let decrypted = str::from_utf8(&decrypted_raw).unwrap_or("not displayable"); - let msg = str::from_utf8(&msg_raw).unwrap_or("not displayable"); - eprintln!( - "[{}] Received message '{}' ({}) from {}", - self.name, decrypted, msg, source.name - ); - } -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 2ab4644..0000000 --- a/src/main.rs +++ /dev/null @@ -1,48 +0,0 @@ -use discrete_logarithm::discrete_log_pollard_rho; -use keygen::Person; -use rug::Integer; -use utils::mod_pow; - -mod keygen; -mod utils; - -fn main() { - let mut alice = Person::new("alice"); - let mut bob = Person::new("bob"); - Person::diffie_hellman(&mut alice, &mut bob); - alice.send(b"Hello World", &bob); - - let alice_priv = discrete_log_pollard_rho( - &Integer::from(alice.r#mod.unwrap()), - &Integer::from(alice.public_key.unwrap()), - &Integer::from(alice.gen.unwrap()), - None, - ).unwrap(); - let bob_priv = discrete_log_pollard_rho( - &Integer::from(bob.r#mod.unwrap()), - &Integer::from(bob.public_key.unwrap()), - &Integer::from(bob.gen.unwrap()), - None, - ); - eprintln!( - "[mallory] Calculated {}'s private key {} from {}'s public key {}", - alice.name, - &alice_priv, - alice.name, - alice.public_key.unwrap() - ); - eprintln!( - "[mallory] Calculated {}'s private key {} from {}'s public key {}", - bob.name, - bob_priv.unwrap(), - bob.name, - bob.public_key.unwrap() - ); - eprintln!( - "[mallory] Calculated {}'s and {}'s shared secret {}", - alice.name, - bob.name, - mod_pow(bob.public_key.unwrap(), alice_priv.to_u32_wrapping(), alice.r#mod.unwrap()) - ); - //Some(mod_pow(public, self.private_key.unwrap(), r#mod -} diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 26f0416..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,28 +0,0 @@ -use num::Integer; - -/** - * Discrete/Modular exponentiation - * - * Highly memory efficient because the full result is never stored, but shortened by defined modulo instead. - * We can use that because the prime divisor required for our algorithm is guarenteed to be smaller - * than n. - * - * Counterpart function to the discrete logarithm. - */ -pub fn mod_pow(mut base: T, mut exp: T, r#mod: T) -> T -where - T: Integer + Copy + std::ops::DivAssign + From, - u64: From, - u128: From, -{ - let mut result: T = T::one(); - base = base % r#mod; - while exp > T::zero() { - if exp.is_odd() { - result = (result * base) % r#mod; - } - base = (base * base) % r#mod; - exp /= T::from(2); - } - result -}