91 lines
No EOL
1.9 KiB
Rust
91 lines
No EOL
1.9 KiB
Rust
use num_bigint_dig::{ToBigUint, RandBigInt, BigUint};
|
|
use num_bigint_dig::traits::ModInverse;
|
|
|
|
fn get_s_and_d(n: &BigUint) -> (BigUint, BigUint) {
|
|
let mut d = n - 1.to_biguint().unwrap();
|
|
let mut s = 0.to_biguint().unwrap();
|
|
|
|
while &d % 2.to_biguint().unwrap() == 0.to_biguint().unwrap() {
|
|
s += 1.to_biguint().unwrap();
|
|
d /= 2.to_biguint().unwrap();
|
|
}
|
|
|
|
(d, s)
|
|
}
|
|
|
|
fn miller_witness(n: &BigUint, a: &BigUint) -> bool {
|
|
let (d, s) = get_s_and_d(&n);
|
|
|
|
let mut x = a.modpow(&d, &n);
|
|
|
|
if x == 1.to_biguint().unwrap() {
|
|
return false;
|
|
}
|
|
|
|
let mut i = 0.to_biguint().unwrap();
|
|
while i < s.clone(){
|
|
if x == n.clone() - 1.to_biguint().unwrap() {
|
|
return false;
|
|
}
|
|
|
|
x = x.modpow(&2.to_biguint().unwrap(), &n);
|
|
|
|
i += 1.to_biguint().unwrap();
|
|
}
|
|
|
|
true
|
|
}
|
|
|
|
fn is_prime(n: BigUint, k: u16) -> bool {
|
|
|
|
if n.clone() == 3.to_biguint().unwrap() || n.clone() == 2.to_biguint().unwrap() {
|
|
return true;
|
|
}
|
|
if n.clone() == 1.to_biguint().unwrap() {
|
|
return false;
|
|
}
|
|
if n.clone() % 2.to_biguint().unwrap() == 0.to_biguint().unwrap() {
|
|
return false;
|
|
}
|
|
|
|
for _ in 0..k {
|
|
let mut rng = rand::thread_rng();
|
|
let min = 2.to_biguint().unwrap();
|
|
let max = n.clone() - 1.to_biguint().unwrap();
|
|
let a = rng.gen_biguint_range(&min, &max);
|
|
|
|
if miller_witness(&n, &a) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
fn gen_prime_number(lenght: usize) -> BigUint {
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut a = rng.gen_biguint(lenght);
|
|
|
|
while !is_prime(a.clone(), 50) {
|
|
a = rng.gen_biguint(lenght);
|
|
}
|
|
|
|
a
|
|
}
|
|
|
|
pub fn gen_keys(lenght: usize) -> (BigUint, BigUint, BigUint) {
|
|
let p = gen_prime_number(lenght / 2);
|
|
let mut q = gen_prime_number(lenght / 2);
|
|
|
|
while p == q {
|
|
q = gen_prime_number(lenght / 2);
|
|
}
|
|
|
|
let n = &p * &q;
|
|
let phi_n = (&p - 1.to_biguint().unwrap()) * (&q - 1.to_biguint().unwrap());
|
|
let e = 65537.to_biguint().unwrap();
|
|
let d = e.clone().mod_inverse(&phi_n).unwrap().to_biguint().expect("error");
|
|
|
|
(e, d, n)
|
|
} |