crypto_bigint/uint/boxed/
rand.rs1use super::BoxedUint;
4use crate::{
5 NonZero, RandomBits, RandomBitsError, RandomMod,
6 uint::rand::{random_bits_core, random_mod_vartime_core},
7};
8use rand_core::{Rng, TryRng};
9
10impl RandomBits for BoxedUint {
11 fn try_random_bits<R: TryRng + ?Sized>(
12 rng: &mut R,
13 bit_length: u32,
14 ) -> Result<Self, RandomBitsError<R::Error>> {
15 Self::try_random_bits_with_precision(rng, bit_length, bit_length)
16 }
17
18 fn try_random_bits_with_precision<R: TryRng + ?Sized>(
19 rng: &mut R,
20 bit_length: u32,
21 bits_precision: u32,
22 ) -> Result<Self, RandomBitsError<R::Error>> {
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, bit_length).map_err(RandomBitsError::RandCore)?;
32 Ok(ret)
33 }
34}
35
36impl RandomMod for BoxedUint {
37 fn random_mod_vartime<R: Rng + ?Sized>(rng: &mut R, modulus: &NonZero<Self>) -> Self {
38 let mut n = BoxedUint::zero_with_precision(modulus.bits_precision());
39 let Ok(()) = random_mod_vartime_core(rng, &mut n, modulus, modulus.bits());
40 n
41 }
42
43 fn try_random_mod_vartime<R: TryRng + ?Sized>(
44 rng: &mut R,
45 modulus: &NonZero<Self>,
46 ) -> Result<Self, R::Error> {
47 let mut n = BoxedUint::zero_with_precision(modulus.bits_precision());
48 random_mod_vartime_core(rng, &mut n, modulus, modulus.bits())?;
49 Ok(n)
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use crate::{BoxedUint, NonZero, RandomBits, RandomMod};
56 use rand_core::SeedableRng;
57
58 #[test]
59 fn random() {
60 let mut rng = chacha20::ChaCha8Rng::seed_from_u64(1);
61
62 let r = BoxedUint::random_bits(&mut rng, 256);
63 assert!(r.bits_precision() == 256);
64
65 let r = BoxedUint::random_bits(&mut rng, 256 - 32 + 1);
66 assert!(r.bits_precision() == 256);
67 assert!(r < BoxedUint::one_with_precision(256) << (256 - 32 + 1));
68 }
69
70 #[test]
71 fn random_mod_vartime() {
72 let mut rng = chacha20::ChaCha8Rng::seed_from_u64(1);
73
74 let modulus = NonZero::new(BoxedUint::from(42u8)).unwrap();
76 let res = BoxedUint::random_mod_vartime(&mut rng, &modulus);
77
78 assert!(res < BoxedUint::from(42u8));
80
81 let modulus = NonZero::new(BoxedUint::from(0x10000000000000001u128)).unwrap();
84 let res = BoxedUint::random_mod_vartime(&mut rng, &modulus);
85
86 assert!(res < BoxedUint::from(0x10000000000000001u128));
88 }
89}