This commit is contained in:
jacekpoz 2024-05-12 19:54:03 +02:00
commit 72176084b0
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
7 changed files with 307 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
l2/
l3/

2
l4/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
z2/
*.zip

1
l4/z1/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.jpg

1
l4/z1/rsa-rs/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

112
l4/z1/rsa-rs/Cargo.lock generated Normal file
View file

@ -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"

9
l4/z1/rsa-rs/Cargo.toml Normal file
View file

@ -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"

180
l4/z1/rsa-rs/src/main.rs Normal file
View file

@ -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<KeyPair> {
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(");
}
}