1#![cfg_attr(not(test), no_std)]
27#![cfg_attr(docsrs, feature(doc_cfg))]
28
29use core::fmt;
30use rand_core::{Rng, SeedableRng, TryCryptoRng, TryRng};
31
32pub struct ReseedingRng<R, Rsdr> {
91 inner: R,
92 reseeder: Rsdr,
93 threshold: usize,
94 bytes_consumed: usize,
95}
96
97impl<R, Rsdr> ReseedingRng<R, Rsdr>
98where
99 R: SeedableRng,
100 Rsdr: TryRng,
101{
102 #[track_caller]
113 pub fn try_new(threshold: usize, mut reseeder: Rsdr) -> Result<Self, Rsdr::Error> {
114 assert!(threshold > 0, "`threshold` must be greater than zero");
115 R::try_from_rng(&mut reseeder).map(|inner| Self {
116 inner,
117 reseeder,
118 threshold,
119 bytes_consumed: 0,
120 })
121 }
122
123 pub fn try_reseed(&mut self) -> Result<(), Rsdr::Error> {
129 R::try_from_rng(&mut self.reseeder).map(|inner| {
130 self.inner = inner;
131 self.bytes_consumed = 0;
132 })
133 }
134
135 #[cold]
136 fn reset_after_reseed_attempt_at(&mut self, pos: usize) {
137 let _ = self.try_reseed();
141 self.bytes_consumed = pos;
142 }
143}
144
145impl<R, Rsdr> TryRng for ReseedingRng<R, Rsdr>
146where
147 R: TryRng + SeedableRng,
148 Rsdr: TryRng,
149{
150 type Error = R::Error;
151
152 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
153 self.bytes_consumed += 32 / 8;
154 if self.bytes_consumed > self.threshold {
155 self.reset_after_reseed_attempt_at(32 / 8);
156 }
157 self.inner.try_next_u32()
158 }
159
160 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
161 self.bytes_consumed += 64 / 8;
162 if self.bytes_consumed > self.threshold {
163 self.reset_after_reseed_attempt_at(64 / 8);
164 }
165 self.inner.try_next_u64()
166 }
167
168 fn try_fill_bytes(&mut self, mut dst: &mut [u8]) -> Result<(), Self::Error> {
169 loop {
170 if self.bytes_consumed + dst.len() <= self.threshold {
171 self.bytes_consumed += dst.len();
172 break self.inner.try_fill_bytes(dst);
173 }
174 if self.bytes_consumed < self.threshold {
175 let mid = self.threshold - self.bytes_consumed;
176 self.bytes_consumed += mid;
177 self.inner.try_fill_bytes(&mut dst[..mid])?;
178 dst = &mut dst[mid..];
179 }
180 self.reset_after_reseed_attempt_at(0);
181 }
182 }
183}
184
185impl<R, Rsdr> TryCryptoRng for ReseedingRng<R, Rsdr>
186where
187 R: TryCryptoRng + SeedableRng,
188 Rsdr: TryCryptoRng,
189{
190}
191
192impl<R, Rsdr> Clone for ReseedingRng<R, Rsdr>
194where
195 R: SeedableRng,
196 Rsdr: Clone + Rng,
197{
198 fn clone(&self) -> Self {
199 let mut reseeder = self.reseeder.clone();
200 Self {
201 inner: R::from_rng(&mut reseeder),
202 reseeder,
203 threshold: self.threshold,
204 bytes_consumed: 0,
205 }
206 }
207}
208
209impl<R, Rsdr> fmt::Debug for ReseedingRng<R, Rsdr>
210where
211 R: fmt::Debug,
212 Rsdr: fmt::Debug,
213{
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
215 f.debug_struct("ReseedingRng")
216 .field("inner", &self.inner)
217 .field("reseeder", &self.reseeder)
218 .field("threshold", &self.threshold)
219 .finish_non_exhaustive()
220 }
221}
222
223#[cfg(feature = "std_rng")]
224mod std_rng;
225
226#[cfg(feature = "std_rng")]
227pub use std_rng::StdReseedingRng;
228
229#[cfg(feature = "std_rng")]
230#[doc(no_inline)]
231pub use rand::RngExt; #[cfg(test)]
234mod mock;
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239 use rand::rngs::{StdRng, SysRng};
240
241 #[test]
242 fn mirror_rand09_reseeding_rng() {
243 use rand_chacha09::{ChaCha12Core, ChaCha12Rng};
244 use rand09::{RngCore as _, SeedableRng as _};
245
246 use mock::Rand09Adapter as Adapter;
247
248 type OurImpl = ReseedingRng<Adapter, Adapter>;
249 type TheirImpl = rand09::rngs::ReseedingRng<ChaCha12Core, ChaCha12Rng>;
250
251 const N: usize = 1024 * 16 * 5 + 997;
252
253 let seed = rand09::random();
254 let mut o = OurImpl::try_new(1024 * 16, Adapter::from_seed(seed)).unwrap();
255 let mut t = TheirImpl::new(1024 * 16, ChaCha12Rng::from_seed(seed)).unwrap();
256
257 for _ in 0..(N / 4) {
258 assert_eq!(o.next_u32(), t.next_u32());
259 }
260
261 o.try_reseed().unwrap();
262 t.reseed().unwrap();
263
264 for _ in 0..(N / 8) {
265 assert_eq!(o.next_u64(), t.next_u64());
266 }
267
268 o.try_reseed().unwrap();
269 t.reseed().unwrap();
270
271 let mut buf_o = vec![0u8; 17 * 4];
272 let mut buf_t = vec![0u8; buf_o.len()];
273 for _ in 0..(N / buf_o.len()) {
274 o.fill_bytes(&mut buf_o[..]);
275 t.fill_bytes(&mut buf_t[..]);
276 assert_eq!(buf_o, buf_t);
277 }
278
279 o.try_reseed().unwrap();
280 t.reseed().unwrap();
281
282 buf_o.resize(1024 * 16 * 2 + 7 * 4, 0);
283 buf_t.resize(buf_o.len(), 0);
284 for _ in 0..(N / buf_o.len()) {
285 o.fill_bytes(&mut buf_o[..]);
286 t.fill_bytes(&mut buf_t[..]);
287 assert_eq!(buf_o, buf_t);
288 }
289 }
290
291 #[test]
292 fn reseed_after_threshold() {
293 let seed = rand::random();
294 let mut g1 = StdRng::from_rng(&mut StdRng::from_seed(seed));
295 let mut g2 =
296 ReseedingRng::<StdRng, _>::try_new(1024 * 64, StdRng::from_seed(seed)).unwrap();
297
298 for _ in 0..(64 * 1024 / (32 / 8 + 32 / 8 + 64 / 8)) {
299 assert_eq!(g1.next_u32(), g2.next_u32());
300 assert_eq!(g1.next_u32(), g2.next_u32());
301 assert_eq!(g1.next_u64(), g2.next_u64());
302 }
303
304 assert_ne!(g1.next_u32(), g2.next_u32());
305 assert_ne!(g1.next_u64(), g2.next_u64());
306 }
307
308 #[test]
309 fn count_periodic_reseeds() {
310 use std::cell::Cell;
311
312 struct MockReseeder<'a> {
313 counter: &'a Cell<usize>,
314 }
315
316 impl TryRng for MockReseeder<'_> {
317 type Error = <SysRng as TryRng>::Error;
318
319 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
320 self.counter.set(self.counter.get() + 1);
321 SysRng.try_next_u32()
322 }
323
324 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
325 self.counter.set(self.counter.get() + 1);
326 SysRng.try_next_u64()
327 }
328
329 fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
330 self.counter.set(self.counter.get() + 1);
331 SysRng.try_fill_bytes(dst)
332 }
333 }
334
335 let counter = Cell::new(0);
336 let reseeder = MockReseeder { counter: &counter };
337 let mut rng = ReseedingRng::<StdRng, _>::try_new(10, reseeder).unwrap();
338 assert_eq!(counter.get(), 1);
339
340 rng.fill_bytes(&mut [0u8; 10]);
341 assert_eq!(counter.get(), 1);
342 assert_eq!(rng.bytes_consumed, 10);
343 rng.fill_bytes(&mut [0u8; 1]);
344 assert_eq!(counter.get(), 2);
345 assert_eq!(rng.bytes_consumed, 1);
346 rng.fill_bytes(&mut [0u8; 9]);
347 assert_eq!(counter.get(), 2);
348 assert_eq!(rng.bytes_consumed, 10);
349 rng.fill_bytes(&mut [0u8; 1]);
350 assert_eq!(counter.get(), 3);
351 assert_eq!(rng.bytes_consumed, 1);
352 rng.fill_bytes(&mut [0u8; 25]);
353 assert_eq!(counter.get(), 5);
354 assert_eq!(rng.bytes_consumed, 6);
355
356 rng.next_u32();
357 assert_eq!(counter.get(), 5);
358 assert_eq!(rng.bytes_consumed, 10);
359 rng.next_u32();
360 assert_eq!(counter.get(), 6);
361 assert_eq!(rng.bytes_consumed, 4);
362 rng.next_u32();
363 assert_eq!(counter.get(), 6);
364 assert_eq!(rng.bytes_consumed, 8);
365 rng.next_u32(); assert_eq!(counter.get(), 7);
367 assert_eq!(rng.bytes_consumed, 4);
368
369 rng.fill_bytes(&mut [0u8; 7]);
370 assert_eq!(counter.get(), 8);
371 assert_eq!(rng.bytes_consumed, 1);
372 rng.next_u64();
373 assert_eq!(counter.get(), 8);
374 assert_eq!(rng.bytes_consumed, 9);
375 rng.next_u64(); assert_eq!(counter.get(), 9);
377 assert_eq!(rng.bytes_consumed, 8);
378 }
379
380 #[test]
381 #[should_panic]
382 fn panic_if_threshold_is_zero() {
383 let _ = ReseedingRng::<StdRng, _>::try_new(0, SysRng);
384 }
385
386 mod fallible {
388 use super::*;
389
390 const N: usize = 20 * 256;
391
392 #[test]
393 fn generate_random_numbers() {
394 let mut rng = ReseedingRng::<StdRng, _>::try_new(1024, SysRng).unwrap();
395
396 let arrays = (0..N)
397 .map(|_| rng.next_u32().to_le_bytes())
398 .collect::<Vec<_>>();
399 assert!(check_each_byte_for_randomness(&arrays));
400
401 let arrays = (0..N)
402 .map(|_| rng.next_u64().to_le_bytes())
403 .collect::<Vec<_>>();
404 assert!(check_each_byte_for_randomness(&arrays));
405
406 let mut buf = [0u8; 17];
407 let arrays = (0..N)
408 .map(|_| {
409 rng.fill_bytes(buf.as_mut());
410 buf
411 })
412 .collect::<Vec<_>>();
413 assert!(check_each_byte_for_randomness(&arrays));
414 }
415
416 #[test]
417 fn handle_corner_cases() {
418 let mut rng = ReseedingRng::<StdRng, _>::try_new(1, SysRng).unwrap();
419
420 let arrays = (0..N)
421 .map(|_| rng.next_u32().to_le_bytes())
422 .collect::<Vec<_>>();
423 assert!(check_each_byte_for_randomness(&arrays));
424
425 let arrays = (0..N)
426 .map(|_| rng.next_u64().to_le_bytes())
427 .collect::<Vec<_>>();
428 assert!(check_each_byte_for_randomness(&arrays));
429
430 let mut buf = [0u8; 5];
431 let arrays = (0..N)
432 .map(|_| {
433 rng.fill_bytes(buf.as_mut());
434 buf
435 })
436 .collect::<Vec<_>>();
437 assert!(check_each_byte_for_randomness(&arrays));
438
439 let mut buf = [0u8; 0];
440 for _ in 0..N {
441 rng.fill_bytes(buf.as_mut());
442 }
443 }
444 }
445
446 pub(crate) fn check_each_byte_for_randomness<const N: usize>(arrays: &[[u8; N]]) -> bool {
447 (0..N).all(|i| {
448 let mut freq = [0usize; 256];
449 for array in arrays {
450 freq[array[i] as usize] += 1; }
452
453 let expected = arrays.len() as f64 / 256.0;
454 let chi_squared = freq.iter().fold(0.0, |acc, &observed| {
455 let dev = observed as f64 - expected;
456 acc + dev * dev / expected
457 });
458
459 chi_squared < 330.52 })
461 }
462}