1use std::sync::Once;
2
3use getrandom::fill;
4use rand::{CryptoRng, RngCore, SeedableRng, rngs::StdRng};
5
6use crate::RandomNumberGenerator;
7
8struct LazyStdRng {
10 rng: std::sync::Mutex<Option<StdRng>>,
11 init: Once,
12}
13
14impl LazyStdRng {
15 fn new() -> Self {
16 Self {
17 rng: std::sync::Mutex::new(None),
18 init: Once::new(),
19 }
20 }
21
22 fn get_rng(&self) -> std::sync::MutexGuard<'_, Option<StdRng>> {
23 self.init.call_once(|| {
24 let mut seed = [0u8; 32];
25 fill(&mut seed).expect("Failed to seed RNG");
26 let rng = StdRng::from_seed(seed);
27
28 let mut guard = self.rng.lock().expect("Mutex was poisoned");
29 *guard = Some(rng);
30 });
31
32 self.rng.lock().expect("Mutex was poisoned")
33 }
34}
35
36lazy_static::lazy_static! {
37 static ref LAZY_RNG: LazyStdRng = LazyStdRng::new();
38}
39
40pub fn random_data(size: usize) -> Vec<u8> {
43 let mut rng_guard = LAZY_RNG.get_rng();
44 let rng = rng_guard.as_mut().expect("RNG was not initialized");
45 let mut data = vec![0u8; size];
46 rng.fill_bytes(&mut data);
47 data
48}
49
50pub fn fill_random_data(data: &mut [u8]) {
52 let mut rng_guard = LAZY_RNG.get_rng();
53 let rng = rng_guard.as_mut().expect("RNG was not initialized");
54 rng.fill_bytes(data);
55}
56
57pub fn next_u64() -> u64 {
58 let mut rng_guard = LAZY_RNG.get_rng();
59 let rng = rng_guard.as_mut().expect("RNG was not initialized");
60 rng.next_u64()
61}
62
63#[derive(Debug, Clone)]
66pub struct SecureRandomNumberGenerator;
67
68impl RngCore for SecureRandomNumberGenerator {
69 fn next_u32(&mut self) -> u32 { next_u64() as u32 }
70
71 fn next_u64(&mut self) -> u64 { next_u64() }
72
73 fn fill_bytes(&mut self, dest: &mut [u8]) { fill_random_data(dest); }
74}
75
76impl CryptoRng for SecureRandomNumberGenerator {}
77
78impl RandomNumberGenerator for SecureRandomNumberGenerator {
79 fn random_data(&mut self, size: usize) -> Vec<u8> { random_data(size) }
80
81 fn fill_random_data(&mut self, data: &mut [u8]) { fill_random_data(data); }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_random_data() {
90 let data1 = random_data(32);
91 let data2 = random_data(32);
92 let data3 = random_data(32);
93 assert_eq!(data1.len(), 32);
94 assert_ne!(data1, data2);
95 assert_ne!(data1, data3);
96 }
97}