11
11
//! The ChaCha random number generator.
12
12
13
13
use core:: fmt;
14
- use { Rng , SeedableRng , Rand } ;
14
+ use { Rand , Rng , SeedableRng } ;
15
15
use impls;
16
16
17
- const KEY_WORDS : usize = 8 ; // 8 words for the 256-bit key
18
- const STATE_WORDS : usize = 16 ;
17
+ const KEY_WORDS : usize = 8 ; // 8 words for the 256-bit key
18
+ const STATE_WORDS : usize = 16 ;
19
19
const CHACHA_ROUNDS : u32 = 20 ; // Cryptographically secure from 8 upwards as of this writing
20
20
21
21
/// A random number generator that uses the ChaCha20 algorithm [1].
@@ -29,9 +29,9 @@ const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of
29
29
/// Salsa20*](https://cr.yp.to/chacha.html)
30
30
#[ derive( Clone ) ]
31
31
pub struct ChaChaRng {
32
- buffer : [ u32 ; STATE_WORDS ] , // Internal buffer of output
33
- state : [ u32 ; STATE_WORDS ] , // Initial state
34
- index : usize , // Index into state
32
+ buffer : [ u32 ; STATE_WORDS ] , // Internal buffer of output
33
+ state : [ u32 ; STATE_WORDS ] , // Initial state
34
+ index : usize , // Index into state
35
35
}
36
36
37
37
// Custom Debug implementation that does not expose the internal state
@@ -79,7 +79,6 @@ fn core(new: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
79
79
}
80
80
81
81
impl ChaChaRng {
82
-
83
82
/// Create an ChaCha random number generator using the default
84
83
/// fixed key of 8 zero words.
85
84
///
@@ -101,9 +100,9 @@ impl ChaChaRng {
101
100
/// - 2419978656
102
101
pub fn new_unseeded ( ) -> ChaChaRng {
103
102
let mut rng = ChaChaRng {
104
- buffer : [ 0 ; STATE_WORDS ] ,
105
- state : [ 0 ; STATE_WORDS ] ,
106
- index : STATE_WORDS
103
+ buffer : [ 0 ; STATE_WORDS ] ,
104
+ state : [ 0 ; STATE_WORDS ] ,
105
+ index : STATE_WORDS ,
107
106
} ;
108
107
rng. init ( & [ 0 ; KEY_WORDS ] ) ;
109
108
rng
@@ -129,9 +128,9 @@ impl ChaChaRng {
129
128
/// println!("{:?}", ra.next_u32());
130
129
/// ```
131
130
pub fn set_counter ( & mut self , counter_low : u64 , counter_high : u64 ) {
132
- self . state [ 12 ] = ( counter_low >> 0 ) as u32 ;
131
+ self . state [ 12 ] = ( counter_low >> 0 ) as u32 ;
133
132
self . state [ 13 ] = ( counter_low >> 32 ) as u32 ;
134
- self . state [ 14 ] = ( counter_high >> 0 ) as u32 ;
133
+ self . state [ 14 ] = ( counter_high >> 0 ) as u32 ;
135
134
self . state [ 15 ] = ( counter_high >> 32 ) as u32 ;
136
135
self . index = STATE_WORDS ; // force recomputation
137
136
}
@@ -161,7 +160,7 @@ impl ChaChaRng {
161
160
self . state [ 3 ] = 0x6B206574 ;
162
161
163
162
for i in 0 ..KEY_WORDS {
164
- self . state [ 4 + i] = key[ i] ;
163
+ self . state [ 4 + i] = key[ i] ;
165
164
}
166
165
167
166
self . state [ 12 ] = 0 ;
@@ -178,11 +177,17 @@ impl ChaChaRng {
178
177
self . index = 0 ;
179
178
// update 128-bit counter
180
179
self . state [ 12 ] = self . state [ 12 ] . wrapping_add ( 1 ) ;
181
- if self . state [ 12 ] != 0 { return } ;
180
+ if self . state [ 12 ] != 0 {
181
+ return ;
182
+ } ;
182
183
self . state [ 13 ] = self . state [ 13 ] . wrapping_add ( 1 ) ;
183
- if self . state [ 13 ] != 0 { return } ;
184
+ if self . state [ 13 ] != 0 {
185
+ return ;
186
+ } ;
184
187
self . state [ 14 ] = self . state [ 14 ] . wrapping_add ( 1 ) ;
185
- if self . state [ 14 ] != 0 { return } ;
188
+ if self . state [ 14 ] != 0 {
189
+ return ;
190
+ } ;
186
191
self . state [ 15 ] = self . state [ 15 ] . wrapping_add ( 1 ) ;
187
192
}
188
193
}
@@ -216,8 +221,7 @@ impl Rng for ChaChaRng {
216
221
}
217
222
218
223
let ( consumed_u32, filled_u8) =
219
- impls:: fill_via_u32_chunks ( & self . buffer [ self . index ..] ,
220
- & mut dest[ read_len..] ) ;
224
+ impls:: fill_via_u32_chunks ( & self . buffer [ self . index ..] , & mut dest[ read_len..] ) ;
221
225
222
226
self . index += consumed_u32;
223
227
read_len += filled_u8;
@@ -226,7 +230,6 @@ impl Rng for ChaChaRng {
226
230
}
227
231
228
232
impl < ' a > SeedableRng < & ' a [ u32 ] > for ChaChaRng {
229
-
230
233
fn reseed ( & mut self , seed : & ' a [ u32 ] ) {
231
234
* self = Self :: from_seed ( seed) ;
232
235
}
@@ -237,14 +240,14 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
237
240
/// words are used, the remaining are set to zero.
238
241
fn from_seed ( seed : & ' a [ u32 ] ) -> ChaChaRng {
239
242
let mut rng = ChaChaRng {
240
- buffer : [ 0 ; STATE_WORDS ] ,
241
- state : [ 0 ; STATE_WORDS ] ,
242
- index : STATE_WORDS
243
+ buffer : [ 0 ; STATE_WORDS ] ,
244
+ state : [ 0 ; STATE_WORDS ] ,
245
+ index : STATE_WORDS ,
243
246
} ;
244
247
rng. init ( & [ 0u32 ; KEY_WORDS ] ) ;
245
248
// set key in place
246
249
{
247
- let key = & mut rng. state [ 4 .. 4 + KEY_WORDS ] ;
250
+ let key = & mut rng. state [ 4 .. 4 + KEY_WORDS ] ;
248
251
for ( k, s) in key. iter_mut ( ) . zip ( seed. iter ( ) ) {
249
252
* k = * s;
250
253
}
@@ -255,15 +258,14 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
255
258
256
259
impl Rand for ChaChaRng {
257
260
fn rand < R : Rng > ( other : & mut R ) -> ChaChaRng {
258
- let mut key : [ u32 ; KEY_WORDS ] = [ 0 ; KEY_WORDS ] ;
261
+ let mut key: [ u32 ; KEY_WORDS ] = [ 0 ; KEY_WORDS ] ;
259
262
for word in key. iter_mut ( ) {
260
263
* word = other. gen ( ) ;
261
264
}
262
265
SeedableRng :: from_seed ( & key[ ..] )
263
266
}
264
267
}
265
268
266
-
267
269
#[ cfg( test) ]
268
270
mod test {
269
271
use { Rng , SeedableRng } ;
@@ -289,22 +291,54 @@ mod test {
289
291
let mut rng1: ChaChaRng = SeedableRng :: from_seed ( seed) ;
290
292
291
293
let mut results = [ 0u32 ; 16 ] ;
292
- for i in results. iter_mut ( ) { * i = rng1. next_u32 ( ) ; }
293
- let expected = [ 0xade0b876 , 0x903df1a0 , 0xe56a5d40 , 0x28bd8653 ,
294
- 0xb819d2bd , 0x1aed8da0 , 0xccef36a8 , 0xc70d778b ,
295
- 0x7c5941da , 0x8d485751 , 0x3fe02477 , 0x374ad8b8 ,
296
- 0xf4b8436a , 0x1ca11815 , 0x69b687c3 , 0x8665eeb2 ] ;
294
+ for i in results. iter_mut ( ) {
295
+ * i = rng1. next_u32 ( ) ;
296
+ }
297
+ let expected = [
298
+ 0xade0b876 ,
299
+ 0x903df1a0 ,
300
+ 0xe56a5d40 ,
301
+ 0x28bd8653 ,
302
+ 0xb819d2bd ,
303
+ 0x1aed8da0 ,
304
+ 0xccef36a8 ,
305
+ 0xc70d778b ,
306
+ 0x7c5941da ,
307
+ 0x8d485751 ,
308
+ 0x3fe02477 ,
309
+ 0x374ad8b8 ,
310
+ 0xf4b8436a ,
311
+ 0x1ca11815 ,
312
+ 0x69b687c3 ,
313
+ 0x8665eeb2 ,
314
+ ] ;
297
315
assert_eq ! ( results, expected) ;
298
316
299
- for i in results. iter_mut ( ) { * i = rng1. next_u32 ( ) ; }
300
- let expected = [ 0xbee7079f , 0x7a385155 , 0x7c97ba98 , 0x0d082d73 ,
301
- 0xa0290fcb , 0x6965e348 , 0x3e53c612 , 0xed7aee32 ,
302
- 0x7621b729 , 0x434ee69c , 0xb03371d5 , 0xd539d874 ,
303
- 0x281fed31 , 0x45fb0a51 , 0x1f0ae1ac , 0x6f4d794b ] ;
317
+ for i in results. iter_mut ( ) {
318
+ * i = rng1. next_u32 ( ) ;
319
+ }
320
+ let expected = [
321
+ 0xbee7079f ,
322
+ 0x7a385155 ,
323
+ 0x7c97ba98 ,
324
+ 0x0d082d73 ,
325
+ 0xa0290fcb ,
326
+ 0x6965e348 ,
327
+ 0x3e53c612 ,
328
+ 0xed7aee32 ,
329
+ 0x7621b729 ,
330
+ 0x434ee69c ,
331
+ 0xb03371d5 ,
332
+ 0xd539d874 ,
333
+ 0x281fed31 ,
334
+ 0x45fb0a51 ,
335
+ 0x1f0ae1ac ,
336
+ 0x6f4d794b ,
337
+ ] ;
304
338
assert_eq ! ( results, expected) ;
305
339
306
340
307
- let seed: & [ _ ] = & [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
341
+ let seed: & [ _ ] = & [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
308
342
let mut rng2: ChaChaRng = SeedableRng :: from_seed ( seed) ;
309
343
310
344
// Store the 17*i-th 32-bit word,
@@ -315,10 +349,24 @@ mod test {
315
349
rng2. next_u32 ( ) ;
316
350
}
317
351
}
318
- let expected = [ 0xf225c81a , 0x6ab1be57 , 0x04d42951 , 0x70858036 ,
319
- 0x49884684 , 0x64efec72 , 0x4be2d186 , 0x3615b384 ,
320
- 0x11cfa18e , 0xd3c50049 , 0x75c775f6 , 0x434c6530 ,
321
- 0x2c5bad8f , 0x898881dc , 0x5f1c86d9 , 0xc1f8e7f4 ] ;
352
+ let expected = [
353
+ 0xf225c81a ,
354
+ 0x6ab1be57 ,
355
+ 0x04d42951 ,
356
+ 0x70858036 ,
357
+ 0x49884684 ,
358
+ 0x64efec72 ,
359
+ 0x4be2d186 ,
360
+ 0x3615b384 ,
361
+ 0x11cfa18e ,
362
+ 0xd3c50049 ,
363
+ 0x75c775f6 ,
364
+ 0x434c6530 ,
365
+ 0x2c5bad8f ,
366
+ 0x898881dc ,
367
+ 0x5f1c86d9 ,
368
+ 0xc1f8e7f4 ,
369
+ ] ;
322
370
assert_eq ! ( results, expected) ;
323
371
}
324
372
@@ -329,16 +377,46 @@ mod test {
329
377
let mut results = [ 0u8 ; 32 ] ;
330
378
rng. fill_bytes ( & mut results) ;
331
379
// Same as first values in test_isaac_true_values as bytes in LE order
332
- let expected = [ 118 , 184 , 224 , 173 , 160 , 241 , 61 , 144 ,
333
- 64 , 93 , 106 , 229 , 83 , 134 , 189 , 40 ,
334
- 189 , 210 , 25 , 184 , 160 , 141 , 237 , 26 ,
335
- 168 , 54 , 239 , 204 , 139 , 119 , 13 , 199 ] ;
380
+ let expected = [
381
+ 118 ,
382
+ 184 ,
383
+ 224 ,
384
+ 173 ,
385
+ 160 ,
386
+ 241 ,
387
+ 61 ,
388
+ 144 ,
389
+ 64 ,
390
+ 93 ,
391
+ 106 ,
392
+ 229 ,
393
+ 83 ,
394
+ 134 ,
395
+ 189 ,
396
+ 40 ,
397
+ 189 ,
398
+ 210 ,
399
+ 25 ,
400
+ 184 ,
401
+ 160 ,
402
+ 141 ,
403
+ 237 ,
404
+ 26 ,
405
+ 168 ,
406
+ 54 ,
407
+ 239 ,
408
+ 204 ,
409
+ 139 ,
410
+ 119 ,
411
+ 13 ,
412
+ 199 ,
413
+ ] ;
336
414
assert_eq ! ( results, expected) ;
337
415
}
338
416
339
417
#[ test]
340
418
fn test_chacha_clone ( ) {
341
- let seed: & [ _ ] = & [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
419
+ let seed: & [ _ ] = & [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
342
420
let mut rng: ChaChaRng = SeedableRng :: from_seed ( seed) ;
343
421
let mut clone = rng. clone ( ) ;
344
422
for _ in 0 ..16 {
0 commit comments