1use alloc::vec::Vec;
2use rand;
3
4use std::collections::HashSet;
5
6extern crate alloc;
7use num_bigint::{BigUint, ModInverse, RandPrime};
8
9
10use core::str::FromStr;
11use num_traits::{One, Zero};
12use rand_core::CryptoRngCore;
13
14pub mod subroutines;
15pub mod proofs;
16pub mod witnesses;
17pub mod hashing;
18
19
20pub type Result<T> = core::result::Result<T, Error>;
21
22#[derive(Debug, Eq, PartialEq)]
23#[non_exhaustive]
24pub enum Error {
25 InvalidPrime,
26 NprimesTooSmall,
27 TooFewPrimes,
28
29}
30
31pub struct RsaPrivateKeyComponents {
32 pub n: BigUint,
33 pub e: BigUint,
34 pub d: BigUint,
35 pub primes: Vec<BigUint>,
36}
37
38
39
40#[inline]
41pub(crate) fn compute_private_exponent_euler_totient(
42 primes: &[BigUint],
43 exp: &BigUint,
44) -> Result<BigUint> {
45 if primes.len() < 2 {
46 return Result::Err(Error::InvalidPrime);
47 }
48
49 let mut totient = BigUint::one();
50
51 for prime in primes {
52 totient *= prime - BigUint::one();
53 }
54
55 if let Some(d) = exp.mod_inverse(totient) {
58 Ok(d.to_biguint().unwrap())
59 } else {
60 Err(Error::InvalidPrime)
62 }
63}
64
65pub fn generate_multi_prime_key_with_exp<R: CryptoRngCore + ?Sized>(
66 rng: &mut R,
67 nprimes: usize,
68 bit_size: usize,
69 exp: &BigUint,
70) -> Result<RsaPrivateKeyComponents> {
71 if nprimes < 2 {
72 return Err(Error::NprimesTooSmall);
73 }
74
75 if bit_size < 64 {
76 let prime_limit = (1u64 << (bit_size / nprimes) as u64) as f64;
77
78 let mut pi = prime_limit / (prime_limit.ln() - 1f64);
80 pi /= 4f64;
82 pi /= 2f64;
85
86 if pi < nprimes as f64 {
87 return Err(Error::TooFewPrimes);
88 }
89 }
90
91 let mut primes = vec![BigUint::zero(); nprimes];
92 let n_final: BigUint;
93 let d_final: BigUint;
94
95 'next: loop {
96 let mut todo = bit_size;
97 if nprimes >= 7 {
109 todo += (nprimes - 2) / 5;
110 }
111
112 for (i, prime) in primes.iter_mut().enumerate() {
113 *prime = rng.gen_prime(todo / (nprimes - i));
114 todo -= prime.bits();
115 }
116
117 for (i, prime1) in primes.iter().enumerate() {
119 for prime2 in primes.iter().take(i) {
120 if prime1 == prime2 {
121 continue 'next;
122 }
123 }
124 }
125
126 let n = subroutines::prime_product(&primes);
127
128 if n.bits() != bit_size {
129 continue 'next;
133 }
134
135 if let Ok(d) = compute_private_exponent_euler_totient(&primes, exp) {
136 n_final = n;
137 d_final = d;
138 break;
139 }
140 }
141
142 Result::Ok(RsaPrivateKeyComponents {
143 n: n_final,
144 e: exp.clone(),
145 d: d_final,
146 primes,
147 })
148}
149
150pub fn gen_diff_prime_vec(k: usize, bits: usize, s: &mut Vec<BigUint>) {
151 let mut rng = rand::thread_rng();
152 let mut set = HashSet::new();
153 let mut i = 0;
154 if k == 0 {
155 return;
156 }
157 loop {
158 let gi = rng.gen_prime(bits);
159 let si = gi;
160 if set.contains(&si) {
161 continue;
162 }
163 set.insert(si);
164 i += 1;
165 if i >= k { break; }
166 }
167 for x in set {
168 s.push(x);
169 }
170}
171
172pub const EXP: u64 = 65537;
173
174pub const MODULUS: &str = "13";
177
178pub const LAMBDA: u32 = u32::max_value();
180
181#[derive(Clone, PartialEq, Debug)]
182pub struct BezoutPairBigUint {
183 pub coefficient_a: BigUint,
184 pub coefficient_b: BigUint,
185 sign_a: bool, sign_b: bool,
187}
188
189
190pub fn add(state: BigUint, elem: BigUint) -> BigUint {
192 return subroutines::mod_exp_big_uint(&state, &elem, &BigUint::from_str(MODULUS).unwrap());
193}
194
195pub fn delete(state: BigUint, elem: BigUint, proof: BigUint) -> Option<BigUint> {
197 if subroutines::mod_exp_big_uint(&proof, &elem, &BigUint::from_str(MODULUS).unwrap()) == state {
198 return Some(proof);
199 }
200 return None;
201}
202
203pub fn batch_delete_by_shamir_trick(state: BigUint, elems: &Vec<(BigUint, BigUint)>) -> (BigUint, BigUint, BigUint) {
206 let (mut x_agg, mut new_state) = elems[0].clone();
207 for i in 1..elems.len() {
208 let (x, witness) = elems[i].clone();
209 new_state = subroutines::shamir_trick_big_uint(new_state, witness, x_agg.clone(), x.clone()).unwrap();
210 x_agg *= x;
211 }
212 let proof = proofs::poe_big_uint(&new_state, &x_agg, &state);
213 return (new_state, x_agg, proof);
214}
215
216pub fn batch_delete_by_normal_loop(base_state: BigUint, state: BigUint, elems_pair: &Vec<(BigUint, BigUint)>, elems: &Vec<BigUint>) -> (BigUint, BigUint, BigUint) {
217 let (mut x_agg, mut new_state) = elems_pair[0].clone();
218 if elems_pair.len() == 1 {
219 return (new_state, x_agg, BigUint::from(1u8));
220 }
221 for i in 1 .. elems_pair.len() {
222 x_agg *= elems_pair[i].clone().0;
223 }
224
225 let new_wi_list = subroutines::root_factor_big_uint(base_state.clone(), &elems[elems_pair.len()-1..]);
226 new_state = new_wi_list.get(0).or_else(|| Some(&new_state)).unwrap().clone();
227
228 let proof = proofs::poe_big_uint(&new_state, &x_agg, &state);
229 return (new_state, x_agg, proof);
230
231}
232
233
234
235pub fn batch_auth_by_shamir_trick(vpks: &Vec<BigUint>, vms: &Vec<BigUint>, new_state: &BigUint) -> bool {
236 subroutines::shamir_batch_big_uint(vpks, vms, new_state)
237}
238
239
240pub fn batch_auth_by_normal_loop(vpks: &Vec<BigUint>, vms: &Vec<BigUint>, new_state: &BigUint) -> bool {
241 subroutines::loop_batch_big_uint(vpks, vms, new_state)
242}
243
244
245pub fn batch_add_big_uint(state: &BigUint, elems: &Vec<BigUint>) -> (BigUint, BigUint, BigUint) {
248 let mut x_agg = BigUint::from(1u8);
249 for i in 0..elems.len() {
250 x_agg *= &elems[i];
251 }
252
253 let new_state = subroutines::mod_exp_big_uint(state, &x_agg, &BigUint::from_str(MODULUS).unwrap());
254 return (new_state, x_agg, BigUint::from(1u8));
257}
258
259
260
261#[cfg(test)]
262mod tests{
263 use num_bigint::BigUint;
264 use crate::{generate_multi_prime_key_with_exp, EXP};
265
266 #[test]
267 fn gen_prims(){
268 let prime_key_with_exp = generate_multi_prime_key_with_exp(&mut rand::thread_rng(),
269 3,
270 56,
271 &BigUint::from(EXP));
272 let key_components = prime_key_with_exp.unwrap();
273 println!("{}", &key_components.n);
274 println!("{}", &key_components.e);
275 println!("{}", &key_components.d);
276 println!("{:?}", &key_components.primes);
277
278 }
279
280
281}
282
283