crypto_bigint/uint/boxed/
rand.rs

1//! Random number generator support.
2
3use super::BoxedUint;
4use crate::{
5    uint::rand::{random_bits_core, random_mod_core},
6    NonZero, RandomBits, RandomBitsError, RandomMod,
7};
8use rand_core::RngCore;
9
10impl RandomBits for BoxedUint {
11    fn try_random_bits(
12        rng: &mut (impl RngCore + ?Sized),
13        bit_length: u32,
14    ) -> Result<Self, RandomBitsError> {
15        Self::try_random_bits_with_precision(rng, bit_length, bit_length)
16    }
17
18    fn try_random_bits_with_precision(
19        rng: &mut (impl RngCore + ?Sized),
20        bit_length: u32,
21        bits_precision: u32,
22    ) -> Result<Self, RandomBitsError> {
23        if bit_length > bits_precision {
24            return Err(RandomBitsError::BitLengthTooLarge {
25                bit_length,
26                bits_precision,
27            });
28        }
29
30        let mut ret = BoxedUint::zero_with_precision(bits_precision);
31        random_bits_core(rng, &mut ret.limbs, bit_length)?;
32        Ok(ret)
33    }
34}
35
36impl RandomMod for BoxedUint {
37    fn random_mod(rng: &mut (impl RngCore + ?Sized), modulus: &NonZero<Self>) -> Self {
38        let mut n = BoxedUint::zero_with_precision(modulus.bits_precision());
39        random_mod_core(rng, &mut n, modulus, modulus.bits());
40        n
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use crate::{BoxedUint, NonZero, RandomBits, RandomMod};
47    use rand_core::SeedableRng;
48
49    #[test]
50    fn random() {
51        let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1);
52
53        let r = BoxedUint::random_bits(&mut rng, 256);
54        assert!(r.bits_precision() == 256);
55
56        let r = BoxedUint::random_bits(&mut rng, 256 - 32 + 1);
57        assert!(r.bits_precision() == 256);
58        assert!(r < BoxedUint::one_with_precision(256) << (256 - 32 + 1));
59    }
60
61    #[test]
62    fn random_mod() {
63        let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1);
64
65        // Ensure `random_mod` runs in a reasonable amount of time
66        let modulus = NonZero::new(BoxedUint::from(42u8)).unwrap();
67        let res = BoxedUint::random_mod(&mut rng, &modulus);
68
69        // Check that the value is in range
70        assert!(res < BoxedUint::from(42u8));
71
72        // Ensure `random_mod` runs in a reasonable amount of time
73        // when the modulus is larger than 1 limb
74        let modulus = NonZero::new(BoxedUint::from(0x10000000000000001u128)).unwrap();
75        let res = BoxedUint::random_mod(&mut rng, &modulus);
76
77        // Check that the value is in range
78        assert!(res < BoxedUint::from(0x10000000000000001u128));
79    }
80}