init
This commit is contained in:
commit
72176084b0
7 changed files with 307 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
l2/
|
||||
l3/
|
2
l4/.gitignore
vendored
Normal file
2
l4/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
z2/
|
||||
*.zip
|
1
l4/z1/.gitignore
vendored
Normal file
1
l4/z1/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.jpg
|
1
l4/z1/rsa-rs/.gitignore
vendored
Normal file
1
l4/z1/rsa-rs/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
112
l4/z1/rsa-rs/Cargo.lock
generated
Normal file
112
l4/z1/rsa-rs/Cargo.lock
generated
Normal 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
9
l4/z1/rsa-rs/Cargo.toml
Normal 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
180
l4/z1/rsa-rs/src/main.rs
Normal 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(");
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue