Skip to main content

crypt_tool/
rng.rs

1use std::ops::Range;
2use std::time::SystemTime;
3
4use std::sync::atomic::{AtomicU32, Ordering};
5use std::sync::Once;
6
7#[derive(Clone)]
8pub struct LCG {
9    a: u32,
10    c: u32,
11    m_mask: u32,
12    seed: u32,
13    state: u32,
14}
15
16impl LCG {
17    fn from_state(state: u32) -> Self {
18        let a: u32 = 1664525;
19        let c: u32 = 1013904223;
20        let m: u32 = 2u32 << 30;
21        Self {
22            a,
23            c,
24            m_mask: m - 1,
25            seed: state,
26            state,
27        }
28    }
29
30    fn cal_state(seeds: &[u8]) -> u32 {
31        seeds.iter().fold(0u32, |acc, &byte| {
32            acc.wrapping_mul(31).wrapping_add(byte as u32)
33        })
34    }
35
36    pub fn from_seed(seed: &[u8]) -> Self {
37        Self::from_state(Self::cal_state(seed))
38    }
39
40    pub fn reset(&mut self) {
41        self.state = self.seed;
42    }
43
44    pub fn generate(&mut self) -> u32 {
45        self.state = (self.a.wrapping_mul(self.state).wrapping_add(self.c)) & self.m_mask;
46        self.state
47    }
48
49    pub fn generate_u8(&mut self) -> u8 {
50        (self.generate() % 256) as u8
51    }
52
53    pub fn rand_range(&mut self, range: Range<usize>) -> usize {
54        let Range { start, end } = range;
55        (self.generate() as usize) % (end - start) + start
56    }
57
58    pub fn generate_random_string(&mut self, len: usize) -> String {
59        const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
60
61        (0..len)
62            .map(|_| CHARSET[self.rand_range(0..CHARSET.len())] as char)
63            .collect::<String>()
64    }
65}
66
67pub fn system_random() -> u32 {
68    // 根据系统时间来生成随机数
69    let now = SystemTime::now()
70        .duration_since(std::time::UNIX_EPOCH)
71        .map(|d| d.as_nanos() % u32::MAX as u128)
72        .unwrap_or(0) as u32;
73
74    let mut rnd = LCG::from_state(now);
75    rnd.generate()
76}
77
78static INIT: Once = Once::new();
79static STATE: AtomicU32 = AtomicU32::new(0);
80
81pub fn simple_random() -> u32 {
82    INIT.call_once(|| {
83        let x = 42u32;
84        let state = &x as *const u32 as u32;
85        STATE.store(state, Ordering::Relaxed);
86    });
87
88    let current_seed = STATE.load(Ordering::Relaxed);
89    let mut lcg = LCG::from_state(current_seed);
90
91    let new_state = lcg.generate();
92
93    STATE.store(new_state, Ordering::Relaxed);
94
95    new_state
96}