diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f2fce95..4d26e95 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -num = "0.4" +num = {version = "0.4", features = ["rand"] } rayon = "1.5" rand = "0.8" \ No newline at end of file diff --git a/rust/notes.md b/rust/notes.md new file mode 100644 index 0000000..ebda9c4 --- /dev/null +++ b/rust/notes.md @@ -0,0 +1,13 @@ +1. n at least 1024 bits +2. p and q 512 bits +3. p and q very different -> p/q !≃ 1 +4. p-1 and q-1 should have a large prime factor +5. p/q should not be close to a rational number +6. do not share n +7. d is leaked change everything +8. optimal e 2^16+1 + +search attack about : +- factorisation +- infer from +- encryption and decryption exponent (small and partial) \ No newline at end of file diff --git a/rust/src/big.rs b/rust/src/big.rs new file mode 100644 index 0000000..f592d72 --- /dev/null +++ b/rust/src/big.rs @@ -0,0 +1,35 @@ +use num::{ BigUint, Integer}; +use crypto_test::prime::miller_rabbin_test_big; +use crypto_test::utils::{ modular_inverse_big }; + +pub fn test(){ + let p = &BigUint::parse_bytes(b"9613034531358350457419158128061542790930984559499621582258315087964794045505647063849125716018034750312098666606492420191808780667421096063354219926661209", 10).unwrap(); + let q = &BigUint::parse_bytes(b"12060191957231446918276794204450896001555925054637033936061798321731482148483764659215389453209175225273226830107120695604602513887145524969000359660045617", 10).unwrap(); + + println!("p prime : {}", miller_rabbin_test_big(p.clone(), 40)); + println!("q prime : {}", miller_rabbin_test_big(q.clone(), 40)); + + let n = p * q; + println!("n : {:?}",n); + let phi = &((p - 1_u16) * (q - 1_u16)); + println!("phi : {:?}",phi); + + + let e = BigUint::parse_bytes(b"65537",10).unwrap(); + println!("e : {:?}",e); + + let inv = modular_inverse_big(e.clone(),phi.clone()).unwrap(); + println!("inv : {:?}",inv); + + let d = inv.mod_floor(phi); + println!("d : {:?}",d); + + let msg = &BigUint::from_bytes_be(b"This is a $up3r test"); + println!("Msg : {:?}", msg); + + let c = msg.modpow(&e,&n); + println!("Encrypted msg : {:?}", c); + + let decrypt = c.modpow(&d,&n); + println!("Decrypted msg : {:?}", decrypt); +} \ No newline at end of file diff --git a/rust/src/main.rs b/rust/src/main.rs index e7a11a9..37d938e 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,3 +1,21 @@ +mod big; + fn main() { - println!("Hello, world!"); + + big::test(); + + + //println!("{:?}",p); + + /*let n = 10; + 'l:for a in 1..n{ + if gcd(a,n) ==1 { + for m in 1..phi(n){ + if congruent(a.pow(m) as i32, 1, n as i32){ + continue 'l; + } + } + println!("ok === > {a}"); + } + }*/ } diff --git a/rust/src/prime.rs b/rust/src/prime.rs index a9bb46a..2af5e15 100644 --- a/rust/src/prime.rs +++ b/rust/src/prime.rs @@ -1,7 +1,9 @@ +use num::{BigUint, One, Zero}; use crate::utils::fast_exp; use num::integer::sqrt; use rand::{thread_rng, Rng}; use rayon::prelude::*; +use rand::distributions::Distribution; pub fn miller_rabbin_gen(max: u32, acr: u32) -> Vec { let method = |n| miller_rabbin_test(n, acr); @@ -41,6 +43,45 @@ fn find_2_k_q(mut n: u32) -> (u32, u32) { } (k, n) } +pub fn miller_rabbin_test_big(n: BigUint, acr: u32) -> bool { + let two = BigUint::one() + BigUint::one(); + let bits = n.bits(); + if &n % &two == BigUint::zero() { + false + } else { + let n_1 = &n-BigUint::one(); + let (k, q) = find_2_k_q_big(n_1.clone()); + let mut random = thread_rng(); + let rb = num::bigint::RandomBits::new(bits); + + 'l: for _ in 0..acr { + let a:BigUint = rb.sample(&mut random) ; + + let mut x = a.modpow(&q,&n); + + if x != BigUint::one() && x != n_1 { + for _ in num::range(BigUint::zero(), &k - BigUint::one()) { + x = x.modpow(&two,&n); + if x == n_1 { + continue 'l; + } + } + return false; + } + } + true + } +} + +fn find_2_k_q_big(mut n: BigUint) -> (BigUint, BigUint) { + let mut k = BigUint::zero(); + let two = BigUint::one() + BigUint::one(); + while &n % &two == BigUint::zero() { + n /= &two; + k += BigUint::one(); + } + (k, n) +} fn prime_gen(max: u32, method: F) -> Vec where diff --git a/rust/src/utils.rs b/rust/src/utils.rs index bb5828d..5ab686d 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -1,3 +1,8 @@ +use num::{BigInt, BigUint, One, Zero}; +use num::bigint::ToBigInt; +use num::integer::gcd; +use rand::{Rng, thread_rng}; + pub fn prime_factor(mut n: u32) -> Vec<(u32, u32)> { let mut p = 2; let mut dec = vec![]; @@ -77,7 +82,25 @@ pub fn modular_inverse(a: u32, n: u32) -> Option { Some(t as u32) } +pub fn modular_inverse_big(a: BigUint, n: BigUint) -> Option { + let (mut t, mut new_t) = (BigInt::zero(), BigInt::one()); + let (mut r, mut new_r) = (n.to_bigint().unwrap(), a.to_bigint().unwrap()); + while new_r != BigInt::zero() { + let q = &r / &new_r; + (t, new_t) = (new_t.clone(), (&t - (&q * &new_t))); + (r, new_r) = (new_r.clone(), (&r - (&q * &new_r))); + } + + if r > BigInt::one() { + return None; + } + if t < BigInt::zero(){ + t += n.to_bigint().unwrap(); + } + + t.to_biguint() +} pub fn fast_exp(mut b: u32, mut e: u32, m: u32) -> u32 { if m == 1 { return 0; @@ -95,6 +118,40 @@ pub fn fast_exp(mut b: u32, mut e: u32, m: u32) -> u32 { result } +pub fn mini_rsa(p: u32, q: u32) -> (u32, u32) { + let mut rnd = thread_rng(); + let phi = (p - 1) * (q - 1); + + let mut d; + let d_inv; + loop { + d = rnd.gen_range(2..phi); + if gcd(d, phi) == 1 { + if let Some(inv) = modular_inverse(d, phi) { + d_inv = inv; + break; + } + } + } + let e = d_inv % phi; + (d, e) +} + +pub fn find_all_rsa(p: u32, q: u32) -> Vec<(u32, u32)> { + let phi = (p - 1) * (q - 1); + let mut v = vec![]; + + for d in 2..phi { + if gcd(d, phi) == 1 { + if let Some(inv) = modular_inverse(d, phi) { + let e = inv % phi; + v.push((d, e)) + } + } + } + v +} + #[cfg(test)] mod tests { use super::*; @@ -147,5 +204,18 @@ mod tests { assert_eq!(fast_exp(11, 13, 19), 11); assert_eq!(fast_exp(1234, 754, 452), 392); assert_eq!(fast_exp(76158, 24586, 5364), 576); + assert_eq!(fast_exp(7, 37_000_000, 11), 1) + } + + #[test] + fn test_mini_rsa() { + let (p, q) = (97, 499); + let n = p * q; + let (d, e) = mini_rsa(q, p); + + let m = 12345; + let c = fast_exp(m, e, n); + let m_d = fast_exp(c, d, n); + assert_eq!(m_d, m); } }