1use rand_core::{CryptoRng, RngCore, SeedableRng};
12
13#[cfg(any(test, feature = "os_rng"))]
14pub(crate) use chacha20::ChaCha12Core as Core;
15
16use chacha20::ChaCha12Rng as Rng;
17
18#[derive(Clone, Debug, PartialEq, Eq)]
70pub struct StdRng(Rng);
71
72impl RngCore for StdRng {
73 #[inline(always)]
74 fn next_u32(&mut self) -> u32 {
75 self.0.next_u32()
76 }
77
78 #[inline(always)]
79 fn next_u64(&mut self) -> u64 {
80 self.0.next_u64()
81 }
82
83 #[inline(always)]
84 fn fill_bytes(&mut self, dst: &mut [u8]) {
85 self.0.fill_bytes(dst)
86 }
87}
88
89impl SeedableRng for StdRng {
90 type Seed = [u8; 32];
92
93 #[inline(always)]
94 fn from_seed(seed: Self::Seed) -> Self {
95 StdRng(Rng::from_seed(seed))
96 }
97}
98
99impl CryptoRng for StdRng {}
100
101#[cfg(test)]
102mod test {
103 use crate::rngs::StdRng;
104 use crate::{Rng, RngCore, SeedableRng};
105
106 #[test]
107 fn test_stdrng_construction() {
108 #[rustfmt::skip]
111 let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
112 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
113
114 let target = [10719222850664546238, 14064965282130556830];
115
116 let mut rng0 = StdRng::from_seed(seed);
117
118 let x0 = rng0.next_u64();
119
120 let mut rng1 = StdRng::from_rng(&mut rng0);
121 let x1 = rng1.next_u64();
122
123 assert_eq!([x0, x1], target);
124 }
125
126 #[test]
127 fn test_chacha_true_values_1() {
128 let seed = [0u8; 32];
135 let mut rng = StdRng::from_seed(seed);
136
137 let mut results = [0u128; 8];
138 rng.fill(&mut results);
139 let expected = [
140 0xd583265f12ce1f8153f955076a9af49b,
141 0x5f15ae2ea589007e1474e049bbc32904,
142 0x798cfaac3428e82cc0e37ad279f86405,
143 0xbe2613412fe80b611969dea02c9f623a,
144 0x3d17e08c3371fc86fe743e204188d50b,
145 0xb489c04c21851515cccbbd19b7eb28c6,
146 0x43c88c1b97b802c611f14ca1cd8d2542,
147 0x1693e617b0a64427c0515190ca461ee9,
148 ];
149 assert_eq!(results, expected);
150
151 assert_eq!(rng.0.get_word_pos(), 32);
152 }
153
154 #[test]
155 fn test_chacha_true_values_2() {
156 let mut seed = [0u8; 32];
160 seed[0] = 1;
161 let mut rng = StdRng::from_seed(seed);
162
163 let mut results = [0u128; 8];
164 rng.fill(&mut results);
165 let expected = [
166 0x9a225cdf090f0eef6b0565d596e0512,
167 0x10dd4d0bff1802930f5d5290278c2449,
168 0xfefdfe067d7a109ee254a4d9392200a6,
169 0xc029dc60c972179bf2f944a0eb0f21f0,
170 0x2a37692ab05e660e2404c6cbc566730c,
171 0xc8a72980b8c4c72a0978bb6fb279f97a,
172 0xaf15ba8e302e43907dfcbb17c23b5154,
173 0xa9177125baafe601560d10ef48eb5ac6,
174 ];
175 assert_eq!(results, expected);
176
177 assert_eq!(rng.0.get_word_pos(), 32);
178 }
179
180 #[test]
181 fn test_chacha_true_values_3() {
182 let seed = [0u8; 32];
186 let mut rng = StdRng::from_seed(seed);
187 rng.0.set_stream(1);
188
189 let mut results = [0u128; 8];
190 rng.fill(&mut results);
191 let expected = [
192 0x3de08d69eff7ba6d4b8c827bf8bdb864,
193 0x6929e19be5ad36988f411457633fb3f8,
194 0xa5995d1de898cb9efccf8ef3a053c946,
195 0xf1d8f021fb3f31ee4b9450a9a8ffced,
196 0x28886a59a2b923fe42c422f2a7b49d55,
197 0x23c72a9150a17ca76e8963134fee2251,
198 0x67b7d07029cb2037e802f6a024bf0bf,
199 0x6fa2523bbd836d3a01c8137c82b91afc,
200 ];
201 assert_eq!(results, expected);
202
203 assert_eq!(rng.0.get_word_pos(), 32);
204 }
205
206 #[test]
207 fn test_chacha_true_values_8() {
208 #[rustfmt::skip]
212 let seed = [
213 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
214 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
215 0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
216 0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d,
217 ];
218 let iv = [0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21];
219 let mut rng = StdRng::from_seed(seed);
220 rng.0.set_stream(u64::from_le_bytes(iv));
221
222 let mut results = [0u128; 8];
223 rng.fill(&mut results);
224 let expected = [
225 0x10c08b11dc3be7b4066dbc8427078214,
226 0xc19c7e1f25aa8669e018a96c7876793c,
227 0x207c8db0992e2d24b483ee160a9a74b2,
228 0xabfb0f9db3b1613b28876c46bc802b09,
229 0x5495b60d624f9e9b32dbebc16b114bd9,
230 0x31d66e96ad465a970c3d47689b3d8e4a,
231 0x3c11e5a1df7a04d8c7ead50a53ff2ae4,
232 0x2ba4a57be08f1cac89d1f183b8e3f391,
233 ];
234 assert_eq!(results, expected);
235
236 assert_eq!(rng.0.get_word_pos(), 32);
237 }
238
239 #[test]
240 fn test_chacha_counter() {
241 let seed = [0u8; 32];
248 let mut rng = StdRng::from_seed(seed);
249 let block = u32::MAX;
250 let words_per_block = 16;
251 rng.0.set_word_pos((block as u128) * words_per_block);
252
253 let mut results = [0u128; 4 * 6];
254 rng.fill(&mut results);
255 let expected = [
256 0xf106e2fcbb524248292ac9f150afa6d7,
257 0x12032ef6c183b50a83a3309513dd017d,
258 0x2c93ff300438eaed6c958a9aa1619382,
259 0x74fc0624270ab858508377945edb52d0,
260 0xe5f4f4a8b8810524264d8911dc537bcc,
261 0x18a6a6cbdc1f823fb1231280056740af,
262 0xabdae0a44b1f45edbccc83dcd3f8638a,
263 0xad6b649f12f70de567cc39740dbb8a22,
264 0x37512785327825dc30ecfaf37a38f5a0,
265 0x5af852d2df0dc286c2dd19af39b54e39,
266 0xb04dc185c27497ac9f4a4f6769d1b5d,
267 0x816492be66439cecd2498c9865284377,
268 0x724fe95e0b6cbb8a55b707c06166147f,
269 0xe3e7cda19d92b5318024abb34aa31329,
270 0x1a3594d7283c077017cd511144bf3db3,
271 0x99ab26cf14f38b11d78e413bdce6424c,
272 0x553deaed89d3bf630de05408c0f655e8,
273 0x86c46a5676fef18f0dc0dff3ee16507c,
274 0xd33d6cf5ade97b000b29e3ce614faf51,
275 0x5b62dcc48c0fc60326afc5783c40d40c,
276 0x44eedc777ed030f43d382d4921eba244,
277 0xa2d66a5893ade34a0d17c706e8d89dba,
278 0xd229d1f3a07526e47cabd035135012fd,
279 0xefae0722059b654dea6945547e535052,
280 ];
281 assert_eq!(results, expected);
282
283 assert_eq!(rng.0.get_word_pos(), (block as u128) * words_per_block + 96);
284 }
285}