Skip to main content

crypto_bigint/limb/
rand.rs

1//! Random number generator support
2
3use super::Limb;
4use crate::{CtLt, Encoding, NonZero, Random, RandomMod};
5use rand_core::TryRng;
6
7impl Random for Limb {
8    fn try_random_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
9        cpubits::cpubits! {
10            32 => { rng.try_next_u32().map(Self) }
11            64 => { rng.try_next_u64().map(Self) }
12        }
13    }
14}
15
16impl RandomMod for Limb {
17    fn try_random_mod_vartime<R: TryRng + ?Sized>(
18        rng: &mut R,
19        modulus: &NonZero<Self>,
20    ) -> Result<Self, R::Error> {
21        let mut bytes = <Self as Encoding>::Repr::default();
22
23        let n_bits = modulus.bits() as usize;
24        let n_bytes = n_bits.div_ceil(8);
25        let mask = 0xffu8 >> (8 * n_bytes - n_bits);
26
27        loop {
28            rng.try_fill_bytes(&mut bytes[..n_bytes])?;
29            bytes[n_bytes - 1] &= mask;
30
31            let n = Limb::from_le_bytes(bytes);
32            if n.ct_lt(modulus).into() {
33                return Ok(n);
34            }
35        }
36    }
37}