commit 72176084b04b0d2b4e00ce824f9b7152c247c24d Author: jacekpoz Date: Sun May 12 19:54:03 2024 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e148fa8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +l2/ +l3/ diff --git a/l4/.gitignore b/l4/.gitignore new file mode 100644 index 0000000..b48bd0f --- /dev/null +++ b/l4/.gitignore @@ -0,0 +1,2 @@ +z2/ +*.zip diff --git a/l4/z1/.gitignore b/l4/z1/.gitignore new file mode 100644 index 0000000..76ce7fc --- /dev/null +++ b/l4/z1/.gitignore @@ -0,0 +1 @@ +*.jpg diff --git a/l4/z1/rsa-rs/.gitignore b/l4/z1/rsa-rs/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/l4/z1/rsa-rs/.gitignore @@ -0,0 +1 @@ +/target diff --git a/l4/z1/rsa-rs/Cargo.lock b/l4/z1/rsa-rs/Cargo.lock new file mode 100644 index 0000000..6750a8e --- /dev/null +++ b/l4/z1/rsa-rs/Cargo.lock @@ -0,0 +1,112 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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 = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", + "rand", +] + +[[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-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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[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 = "rsa" +version = "0.1.0" +dependencies = [ + "num-bigint", + "num-traits", + "rand", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/l4/z1/rsa-rs/Cargo.toml b/l4/z1/rsa-rs/Cargo.toml new file mode 100644 index 0000000..cb6beb2 --- /dev/null +++ b/l4/z1/rsa-rs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rsa" +version = "0.1.0" +edition = "2021" + +[dependencies] +rand = "0.8.5" +num-bigint = { version = "0.4.5", features = [ "rand" ] } +num-traits = "0.2.19" diff --git a/l4/z1/rsa-rs/src/main.rs b/l4/z1/rsa-rs/src/main.rs new file mode 100644 index 0000000..0ce0f88 --- /dev/null +++ b/l4/z1/rsa-rs/src/main.rs @@ -0,0 +1,180 @@ +use rand::thread_rng; +use num_bigint::{BigInt, BigUint, RandBigInt, ToBigInt}; +use num_traits::{One, Zero}; + +#[derive(Clone, Debug, PartialEq)] +struct Key { + n: BigUint, + key: BigUint, +} + +#[derive(Clone, Debug, PartialEq)] +struct KeyPair { + private: Key, + public: Key, +} + +fn is_prime(n: &BigUint) -> bool { + let mut i = BigUint::from(2u32); + while &i < &n.sqrt() { + if n % &i == 0u32.into() { + return false; + } + i += 1u32; + } + true +} + +fn euclid(a: &BigUint, b: &BigUint) -> BigUint { + let mut s0 = BigInt::one(); + let mut s1 = BigInt::zero(); + let mut t0 = BigInt::zero(); + let mut t1 = BigInt::one(); + // SAFETY: according to the docs this will never fail + // https://docs.rs/num-bigint/latest/num_bigint/trait.ToBigInt.html + let mut r0 = a.to_bigint().unwrap(); + let mut r1 = b.to_bigint().unwrap(); + + while r1 != 0.into() { + let q = &r0 / &r1; + let mut temp = r1.clone(); + r1 = r0 - &q * r1; + r0 = temp; + + temp = s1.clone(); + s1 = s0 - &q * s1; + s0 = temp; + + temp = t1.clone(); + t1 = t0 - &q * t1; + t0 = temp; + } + + // SAFETY: this if prevents the result from being negative + if s0 < 0.into() { + (s0 + BigInt::from(b.clone())).to_biguint().unwrap() + } else { + s0.to_biguint().unwrap() + } +} + +fn find_e(phi: &BigUint) -> BigUint { + let mut e = thread_rng().gen_biguint_range(&1u32.into(), phi); + let mut g = gcd(&e, phi); + while g != 1u32.into() { + e = thread_rng().gen_biguint_range(&1u32.into(), phi); + g = gcd(&e, phi); + } + + e +} + +fn generate_key_pair(p: &BigUint, q: &BigUint) -> Option { + if !is_prime(p) || !is_prime(q) || p == q { + return None; + } + + let n = p * q; + let phi = (p - 1u32) * (q - 1u32); + + let e = find_e(&phi); + + let d = euclid(&e, &phi); + + Some( + KeyPair { + private: Key { n: n.clone(), key: d }, + public: Key { n, key: e } + } + ) +} + +fn gcd(a: &BigUint, b: &BigUint) -> BigUint { + if b > a { + return gcd(b, a); + } + let mut a = a.clone(); + let mut b = b.clone(); + let mut r; + while b != BigUint::zero() { + r = a % &b; + a = b; + b = r; + } + a +} + +fn pow_mod(a: &BigUint, exp: &BigUint, n: &BigUint) -> BigUint { + let mut a = a.clone(); + let mut exp = exp.clone(); + let mut res = BigUint::one(); + while exp > BigUint::zero() { + if &exp % 2u32 == 1u32.into() { + res = (res * &a) % n; + } + a = (&a * &a) % n; + exp /= 2u32; + } + res +} + +fn find_private_key(n: &BigUint, e: &BigUint, d: &BigUint) -> (BigUint, BigUint) { + let kphi = d * e - 1u32; + let mut t = kphi.clone(); + while &t % 2u32 == BigUint::zero() { + // println!("t: {t}"); + t /= 2u32; + } + + let mut p = BigUint::one(); + + let mut a = BigUint::from(2u32); + while a < 100u32.into() { + let mut k = t.clone(); + while k < kphi { + // println!("a: {a}, kphi: {kphi}, k: {k}, n: {n}"); + let x = pow_mod(&a, &k, n); + // println!("x: {x}; n: {n}"); + if x != BigUint::one() && + x != (n - 1u32) && + pow_mod(&x, &2u32.into(), n) == BigUint::one() + { + // println!("x: {x}; n: {n}"); + p = gcd(&(x - BigUint::one()), n); + // println!("p: {p}"); + break; + } + k *= 2u32; + } + a += 2u32; + } + + let q = n / &p; + + (p, q) +} + +fn main() { + let p1 = BigUint::from(1234577u32); + let p2 = BigUint::from(1234567891u32); + + let pair_a = generate_key_pair(&p1, &p2) + .expect("failed to generate key pair a"); + + let pair_b = generate_key_pair(&p1, &p2) + .expect("failed to generate key pair b"); + + println!("private key A: {:?}", pair_a.private); + println!("public key A: {:?}", pair_a.public); + println!("private key B: {:?}", pair_b.private); + println!("public key B: {:?}", pair_b.public); + + let found_secret = find_private_key(&pair_a.public.n, &pair_a.public.key, &pair_a.private.key); + println!("found_b: {:?}", found_secret); + if (&found_secret.0 == &p1 && &found_secret.1 == &p2) + || (&found_secret.0 == &p2 && &found_secret.1 == &p1) { + println!("cracked B)"); + } else { + println!("uncracked B("); + } +}