1use std::str::FromStr;
3use rand::Rng;
4use num_bigint::{ToBigUint, BigUint, RandBigInt, BigInt, Sign};
5use num::{Zero, One, Integer};
6use crate::helpers::generics::*;
7
8
9const DISCARTERS: [u8; 7] = [3, 5, 7, 11, 13, 17, 19];
10
11pub fn gen_big_num(bit_len: &u32) -> BigUint {
13 let mut rng = rand::thread_rng();
15 let a = rng.gen_biguint(bit_len.to_owned() as usize);
16 a
17}
18
19pub fn gen_big_prime(size: &u32, threshold: u32) -> BigUint {
22 let mut proposal = gen_big_num(size);
23 if proposal.is_even() {
25 proposal = proposal + BigUint::one();
26 }
27 while !is_prime(&proposal, threshold) {
28 proposal = proposal + 2.to_biguint().unwrap();
30 }
31 proposal
32}
33
34pub fn is_prime(proposal: &BigUint, threshold: u32) -> bool {
37 if !rabin_miller(proposal, threshold) {return false}
38 true
39}
40
41fn rabin_miller(proposal: &BigUint, t: u32) -> bool {
47 let (z, o, tw) = gen_basic_biguints();
49 let (zero, one, two) = (&z, &o, &tw);
50 if proposal.clone() <= one.to_owned() {return false};
52 if proposal.clone() != two.to_owned() && proposal.clone() % two == zero.to_owned() {return false};
54 let discarts: Vec<bool> = DISCARTERS.into_iter().map(|x| (proposal % x.to_biguint().unwrap()).is_zero()).collect();
56 println!("{:?}", discarts);
57 for result in discarts {
58 if result == true {return false}
59 }
60
61 let (s,d) = refactor(proposal);
63
64 let mut counter = 0;
65 while counter < t {
66 let mut rng = rand::thread_rng();
68 let a = rng.gen_biguint_range(&two , &(proposal - two) );
69
70 let mut x = mod_exp_pow(&a, &d, proposal);
71 if x != one.to_owned() && x != proposal.to_owned() - one {
72 let mut i = zero.clone();
73 loop {
74 x = mod_exp_pow(&x, &two, proposal);
75 if x == proposal.to_owned() - one {break;}
76 if x == one.to_owned() || i >= s.clone()- one{return false;};
77
78 i = i.clone() + one;
79 }
80 }
81 counter +=2;
82 }
83 true
84}
85#[cfg(test)]
86#[test]
87fn rabin_miller_works() {
88 let res = rabin_miller(&179425357u32.to_biguint().unwrap(), 9);
90 assert_eq!(res, true);
91 let res2 = rabin_miller(&82589933u32.to_biguint().unwrap(), 64);
92 assert_eq!(res2, true);
93
94
95 let known_prime_str =
97 "118595363679537468261258276757550704318651155601593299292198496313960907653004730006758459999825003212944725610469590674020124506249770566394260832237809252494505683255861199449482385196474342481641301503121142740933186279111209376061535491003888763334916103110474472949854230628809878558752830476310536476569";
98 let known_prime: BigUint = FromStr::from_str(known_prime_str).unwrap();
99 assert!(rabin_miller(&known_prime, 64));
100
101 assert_eq!(rabin_miller(&19u32.to_biguint().unwrap(), 9), false);
102}
103
104pub fn mod_exp_pow(base: &BigUint, exp: &BigUint, md: &BigUint) -> BigUint {
106 let mut res = BigUint::one();
107 let (zero, one, _) = gen_basic_biguints();
108 let (mut base, mut exponent) = (base.clone(), exp.clone());
109
110 while exponent > zero {
111 if exponent.clone() & one.clone() > zero {
112 res = (res * base.clone()) % md;
113 }
114 exponent >>= 1;
116 base = (base.clone() * base.clone()) % md;
118 }
119 res
120}
121
122#[cfg(test)]
123#[test]
124fn mod_exp_works() {
125 let res = mod_exp_pow(&BigUint::from(4 as u32), &BigUint::from(13 as u32), &BigUint::from(497 as u32));
126 assert_eq!(res, BigUint::from(445 as u32));
127
128 let res2 = mod_exp_pow(&BigUint::from(5 as u32), &BigUint::from(3 as u32), &BigUint::from(13 as u32));
129 assert_eq!(res2, BigUint::from(8 as u32));
130}
131
132fn refactor(n: &BigUint) -> (BigUint, BigUint) {
134 let (mut s, one, two) = gen_basic_biguints();
135 let mut d = n.clone() - one.clone();
136
137 while d.is_even() {
138 d = d / two.clone();
139 s = s + one.clone();
140 }
141 (s, d)
142}
143
144pub fn egcd<'a>(a: &'a mut BigInt, b: &'a mut BigInt) -> (BigInt, BigInt, BigInt) {
148 if a.to_owned() == BigInt::from(0 as u32) {
150 (b.clone(), BigInt::from(0 as i32), BigInt::from(1 as i32))
151 } else {
152 let mut b_mod_a = b.clone() % a.clone();
153 let ref_b_mod_a = &mut b_mod_a;
154 let (g, x, y) = egcd(ref_b_mod_a, a);
155 let mut b_div_a = b.clone() / a.clone();
156 let ref_b_div_a = &mut b_div_a;
157 (g, (y - ref_b_div_a.clone() * x.clone()), x)
158 }
159}
160
161#[cfg(test)]
162
163#[test]
164fn egcd_test() {
165 use num_bigint::ToBigInt;
166 use std::str::FromStr;
167
168 let a = &mut 179425357u32.to_bigint().unwrap();
170 let b = &mut 97u32.to_bigint().unwrap();
171 let (g, x, y) = egcd(a, b);
172 assert_eq!(a.clone()*x + b.clone()*y, g);
173
174 let a = &mut 1024u32.to_bigint().unwrap();
176 let b = &mut 512u32.to_bigint().unwrap();
177 let (g, _x, _y) = egcd(a, b);
178 assert_eq!(512u32.to_bigint().unwrap(), g);
179
180 let known_prime_str = "118595363679537468261258276757550704318651155601593299292198496313960907653004730006758459999825003212944725610469590674020124506249770566394260832237809252494505683255861199449482385196474342481641301503121142740933186279111209376061535491003888763334916103110474472949854230628809878558752830476310536476569";
182 let known_prime_str_2 = "357111317192329313741434753596167717379838997101103107109113127131137139149151157163167173179181191193197199211223227229233239241251257263269271277281283293307311313317331337347349353359367373379383389397401409419421431433439443449457461463467479487491499503509521523541547557563569571577587593599601607613617619631641643647653659661673677683691701709719727733739743751757761769773787797809811821823827829839853857859863877881883887907911919929937941947953967971977983991997";
183 let mut a: BigInt = FromStr::from_str(known_prime_str).unwrap();
184 let mut b: BigInt = FromStr::from_str(known_prime_str_2).unwrap();
185 let a_r = &mut a;
186 let b_r = &mut b;
187 let (g, x, y) = egcd(a_r, b_r);
188 assert_eq!(a_r.clone()*x + b_r.clone()*y, g);
189}
190
191pub fn find_e(fi_n: &BigUint) -> Result<BigUint, bool> {
194 let mut rng = rand::thread_rng();
196 let sign = Sign::Plus;
198 let mut fi_n = BigInt::from_biguint(sign, fi_n.clone());
199 let (zero, one, two) = gen_basic_bigints();
200 let mut a = rng.gen_bigint_range(&(fi_n.clone()/two.clone()) , &((BigInt::from(3) * fi_n.clone())/BigInt::from(4) ));
201 if a.is_even() {a = a + one.clone()};
203 let mut res = zero;
204 while res != one.clone() && a <= fi_n.clone() - one.clone() {
205 let (res2, _, _) = egcd(&mut fi_n, &mut a);
206 res = res2;
207 a = a.clone() + two.clone();
208 }
209
210 if res == one {
211 a = a.clone() - two.clone();
212 return Ok(biguint_from_bigint(&a).unwrap());
213 }
214 Err(false)
215}