1pub mod derive_rng;
2pub mod prf;
3pub mod prg;
4pub mod test_rng;
5
6pub use prg::{new_prg, prg, Prng};
7use rand::{distributions::Standard, prelude::Distribution};
8pub use rand_chacha::rand_core::CryptoRngCore;
9use subtle::Choice;
10pub use test_rng::{test_rng, TestRng};
11use typenum::Unsigned;
12
13use crate::{
14 algebra::field::FieldExtension,
15 constants::{CollisionResistanceBytes, Lambda},
16 errors::PrimitiveError,
17 random::derive_rng::DeriveRng,
18 utils::IntoExactSizeIterator,
19};
20
21pub type Seed = [u8; CollisionResistanceBytes::USIZE];
23
24impl DeriveRng for Seed {}
25
26pub trait Random: Sized {
29 fn random(rng: impl CryptoRngCore) -> Self;
31
32 fn random_n<Container: FromIterator<Self>>(
34 mut rng: impl CryptoRngCore,
35 size: usize,
36 ) -> Container {
37 (0..size).map(|_| Self::random(&mut rng)).collect()
38 }
39}
40
41impl<T> Random for T
43where
44 Standard: Distribution<T>,
45{
46 #[inline]
47 fn random(mut source: impl CryptoRngCore) -> Self {
48 Standard.sample(&mut source)
49 }
50}
51
52pub trait RandomWith<D: Clone>: Sized {
54 fn random_with(rng: impl CryptoRngCore, data: D) -> Self;
56
57 fn random_n_with<Container: FromIterator<Self>>(
59 mut rng: impl CryptoRngCore,
60 size: usize,
61 data: D,
62 ) -> Container {
63 (0..size)
64 .map(|_| Self::random_with(&mut rng, data.clone()))
65 .collect()
66 }
67
68 fn random_n_with_each<Container: FromIterator<Self>>(
70 mut rng: impl CryptoRngCore,
71 all_data: impl IntoExactSizeIterator<Item = D>,
72 ) -> Container {
73 all_data
74 .into_iter()
75 .map(|data| Self::random_with(&mut rng, data))
76 .collect()
77 }
78}
79
80pub trait RandomNonZero: Sized {
82 fn random_non_zero(rng: impl CryptoRngCore) -> Result<Self, PrimitiveError>;
84
85 fn random_n_non_zero<Container: FromIterator<Self>>(
87 rng: impl CryptoRngCore,
88 size: usize,
89 ) -> Result<Container, PrimitiveError>;
90}
91
92impl<T: FieldExtension> RandomNonZero for T {
93 #[inline]
108 fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
109 let n_tries = (Lambda::USIZE).div_ceil(std::mem::size_of::<Self>());
110 for _ in 0..n_tries {
111 let value = <Self as ff::Field>::random(&mut rng);
112 if !<Choice as Into<bool>>::into(value.is_zero()) {
113 return Ok(value);
114 }
115 }
116 Err(PrimitiveError::ZeroValueSampled(
117 std::any::type_name::<Self>().into(),
118 ))
119 }
120
121 fn random_n_non_zero<Container: FromIterator<Self>>(
123 mut rng: impl CryptoRngCore,
124 size: usize,
125 ) -> Result<Container, PrimitiveError> {
126 (0..size).map(|_| Self::random_non_zero(&mut rng)).collect()
127 }
128}