Big number and RSA
This commit is contained in:
@@ -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"
|
||||
13
rust/notes.md
Normal file
13
rust/notes.md
Normal file
@@ -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)
|
||||
35
rust/src/big.rs
Normal file
35
rust/src/big.rs
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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}");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -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<u32> {
|
||||
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<F>(max: u32, method: F) -> Vec<u32>
|
||||
where
|
||||
|
||||
@@ -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<u32> {
|
||||
|
||||
Some(t as u32)
|
||||
}
|
||||
pub fn modular_inverse_big(a: BigUint, n: BigUint) -> Option<BigUint> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user