use rand::Rng;
use rug::rand::{RandGen, RandState};
use rug::{Complete, Integer};
use std::cmp::Ordering;
use rand_chacha::ChaCha20Rng;
use rand_chacha::rand_core::{RngCore, SeedableRng};
struct CryptographicallySecurePRNG(ChaCha20Rng);
impl RandGen for CryptographicallySecurePRNG {
fn gen(&mut self) -> u32 {
self.0.next_u32()
}
}
pub fn random_bits(n: u32) -> Integer {
let mut rng = rand::thread_rng();
let seed = rng.gen();
let mut binding = CryptographicallySecurePRNG(ChaCha20Rng::from_seed(seed));
let mut rand = RandState::new_custom(&mut binding);
let mut i = Integer::from(Integer::random_bits(n, &mut rand));
i.set_bit(n - 1, true);
i
}
pub fn random_number(n: Integer) -> Integer {
let mut rng = rand::thread_rng();
let seed = rng.gen();
let mut binding = CryptographicallySecurePRNG(ChaCha20Rng::from_seed(seed));
let mut rand = RandState::new_custom(&mut binding);
let number = n.random_below(&mut rand);
number
}
pub fn random_prime(n: u32) -> Integer {
let r = random_bits(n);
let prime = r.next_prime();
prime
}
pub fn random_qr(n: &Integer) -> Integer {
let mut r = random_number(n.clone());
let mut qr = r.secure_pow_mod(&Integer::from(2), n);
while !(qr.cmp(&Integer::from(1)) == Ordering::Greater
&& qr.clone().gcd(&n).cmp(&Integer::from(1)) == Ordering::Equal)
{
r = random_number(n.clone());
qr = r.secure_pow_mod(&Integer::from(2), n);
}
qr
}
pub fn rand_int(a: Integer, b: Integer) -> Integer {
let mut rng = rand::thread_rng();
let seed = rng.gen();
let mut binding = CryptographicallySecurePRNG(ChaCha20Rng::from_seed(seed));
let mut rand = RandState::new_custom(&mut binding);
let range = (&b - &a).complete() + Integer::from(1);
return a + range.random_below(&mut rand);
}