1#![forbid(unsafe_code)]
2
3mod helpers;
29mod oxirng;
30mod read;
31mod reseeding;
32mod thread_rng;
33
34pub use oxirng::{OxiRng, OxiRng12, OxiRng8};
37pub use reseeding::ReseedingRng;
38
39pub use helpers::{
42 check_entropy, random_bool, random_bool_with_rng, random_bytes, random_nonce, random_range,
43 random_range_to, random_range_unbiased, random_u128, random_u32, random_u64, reseed, shuffle,
44 weighted_choice, weighted_choice_with_rng,
45};
46
47#[cfg(feature = "std")]
48pub use thread_rng::with_thread_rng;
49
50#[cfg(test)]
56pub mod test_rng {
57 use rand_chacha::ChaCha20Rng;
58 use rand_core::{SeedableRng, TryCryptoRng, TryRng};
59
60 use oxicrypto_core::{CryptoError, Rng};
61
62 pub struct TestRng(ChaCha20Rng);
66
67 impl TestRng {
68 pub fn from_seed(seed: [u8; 32]) -> Self {
70 Self(ChaCha20Rng::from_seed(seed))
71 }
72 }
73
74 impl Rng for TestRng {
75 fn fill(&mut self, dst: &mut [u8]) -> Result<(), CryptoError> {
76 use rand_core::TryRng;
77 self.0.try_fill_bytes(dst).map_err(|_| CryptoError::Rng)
78 }
79 }
80
81 impl TryRng for TestRng {
82 type Error = core::convert::Infallible;
83
84 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
85 self.0.try_next_u32()
86 }
87
88 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
89 self.0.try_next_u64()
90 }
91
92 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
93 self.0.try_fill_bytes(dest)
94 }
95 }
96
97 impl TryCryptoRng for TestRng {}
98}
99
100#[cfg(test)]
103mod tests {
104 use super::*;
105 use oxicrypto_core::Rng;
106
107 #[test]
108 fn test_rng_deterministic() {
109 use test_rng::TestRng;
110
111 let seed = [42u8; 32];
112 let mut rng1 = TestRng::from_seed(seed);
113 let mut rng2 = TestRng::from_seed(seed);
114
115 let mut out1 = [0u8; 64];
116 let mut out2 = [0u8; 64];
117 rng1.fill(&mut out1).expect("TestRng fill 1 failed");
118 rng2.fill(&mut out2).expect("TestRng fill 2 failed");
119
120 assert_eq!(out1, out2, "Same seed must produce same output");
121 }
122
123 #[test]
124 fn test_rng_different_seeds_differ() {
125 use test_rng::TestRng;
126
127 let mut rng_a = TestRng::from_seed([1u8; 32]);
128 let mut rng_b = TestRng::from_seed([2u8; 32]);
129
130 let mut out_a = [0u8; 64];
131 let mut out_b = [0u8; 64];
132 rng_a.fill(&mut out_a).expect("TestRng fill a failed");
133 rng_b.fill(&mut out_b).expect("TestRng fill b failed");
134
135 assert_ne!(
136 out_a, out_b,
137 "Different seeds must produce different output"
138 );
139 }
140}