1use std::convert::TryInto;
2use std::time::SystemTime;
3use rand_core::{SeedableRng, RngCore};
4use rand_chacha::ChaCha12Rng;
5
6pub struct SecureRng(ChaCha12Rng);
10
11impl Default for SecureRng {
12 fn default() -> Self {
14 let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
15 Self::with_seed(time.as_millis() as u64)
16 }
17}
18
19impl SecureRng {
20 pub fn with_seed(seed: u64) -> Self {
22 let inner = ChaCha12Rng::seed_from_u64(seed);
23 SecureRng(inner)
24 }
25
26 pub fn with_safe_seed<S, K>(encrypted: S, key: K) -> Self
28 where S: AsRef<[u8]>,
29 K: AsRef<[u8]>,
30 {
31 let unencrypted = xor_encrypt(encrypted, key).unwrap();
32 let seed = u64::from_le_bytes(unencrypted.as_slice().try_into().unwrap());
33 Self::with_seed(seed)
34 }
35
36 pub fn with_confusion_seed<S, K>(encrypted: S, key: K) -> Self
38 where S: AsRef<[u8]>,
39 K: AsRef<[u8]>,
40 {
41 let unencrypted = xor_unencrypt_clarity(encrypted, key).unwrap();
42 let seed = u64::from_le_bytes(unencrypted.as_slice().try_into().unwrap());
43 Self::with_seed(seed)
44 }
45
46 #[inline]
48 pub fn get_u32(&mut self) -> u32 {
49 self.0.next_u32()
50 }
51
52 #[inline]
54 pub fn get_u64(&mut self) -> u64 {
55 self.0.next_u64()
56 }
57}
58
59#[inline]
63pub fn xor_encrypt<T, K>(data: T, key: K) -> Result<Vec<u8>, ()>
64where
65 T: AsRef<[u8]>,
66 K: AsRef<[u8]>,
67{
68 let data = data.as_ref();
69 let key = key.as_ref();
70
71 if key.as_ref().len() < 8 {
72 return Err(());
74 }
75
76 let encrypted = data
77 .iter()
78 .enumerate()
79 .map(|(i, &byte)| byte ^ key[i % key.len()])
80 .collect();
81
82 Ok(encrypted)
83}
84
85#[inline]
89pub fn xor_encrypt_confusion<T, K>(data: T, key: K) -> Result<Vec<u8>, ()>
90where
91 T: AsRef<[u8]>,
92 K: AsRef<[u8]>,
93{
94 let encrypt = xor_encrypt(data, key)?;
95
96 let len = encrypt.len();
97 if len % 2 != 0 {
98 return Err(());
100 }
101
102 let half_len = len / 2;
103 let mut confused = Vec::with_capacity(len);
104 confused.resize(len, 0);
105 for i in 0..len {
106 if i % 2 != 0 {
107 confused[i] = encrypt[i];
108 continue;
109 } else if i < half_len {
110 let j = i + half_len;
111 confused[j] = encrypt[i];
112 confused[i] = encrypt[j];
113 }
114 }
115
116 Ok(confused)
117}
118
119#[inline]
123pub fn xor_unencrypt_clarity<T, K>(data: T, key: K) -> Result<Vec<u8>, ()>
124where
125 T: AsRef<[u8]>,
126 K: AsRef<[u8]>,
127{
128 let encrypt = data.as_ref();
129 let len = encrypt.len();
130 if len % 2 != 0 {
131 return Err(());
133 }
134
135 let half_len = len / 2;
136 let mut clarified = Vec::with_capacity(len);
137 clarified.resize(len, 0);
138 for i in 0..len {
139 if i % 2 != 0 {
140 clarified[i] = encrypt[i];
141 continue;
142 } else if i < half_len {
143 let j = i + half_len;
144 clarified[j] = encrypt[i];
145 clarified[i] = encrypt[j];
146 }
147 }
148
149 let unencrypt = xor_encrypt(clarified, key)?;
150
151 Ok(unencrypt)
152}
153