bc_rand/
secure_random.rs

1use std::sync::Once;
2
3use getrandom::fill;
4use rand::{CryptoRng, RngCore, SeedableRng, rngs::StdRng};
5
6use crate::RandomNumberGenerator;
7
8// A wrapper for lazy RNG initialization and thread safety
9struct 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
40/// Generate a vector of cryptographically strong random bytes of the given
41/// size.
42pub 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
50/// Fill the given slice with cryptographically strong random bytes.
51pub 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/// A random number generator that can be used as a source of
64/// cryptographically-strong randomness.
65#[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}