1use std::sync::Once;
2
3use getrandom::getrandom;
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 getrandom(&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 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
76 self.fill_bytes(dest);
77 Ok(())
78 }
79}
80
81impl CryptoRng for SecureRandomNumberGenerator {}
82
83impl RandomNumberGenerator for SecureRandomNumberGenerator {
84 fn random_data(&mut self, size: usize) -> Vec<u8> { random_data(size) }
85
86 fn fill_random_data(&mut self, data: &mut [u8]) { fill_random_data(data); }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_random_data() {
95 let data1 = random_data(32);
96 let data2 = random_data(32);
97 let data3 = random_data(32);
98 assert_eq!(data1.len(), 32);
99 assert_ne!(data1, data2);
100 assert_ne!(data1, data3);
101 }
102}