10
10
11
11
//! The HC-128 random number generator.
12
12
13
- use core:: fmt;
14
- use core:: slice;
15
-
13
+ use core:: { fmt, slice} ;
16
14
use { Rng , SeedableRng , Rand } ;
17
15
use impls;
18
16
17
+ const SEED_WORDS : usize = 8 ; // 128 bit key followed by 128 bit iv
18
+
19
19
/// A cryptographically secure random number generator that uses the HC-128
20
20
/// algorithm.
21
21
///
@@ -39,6 +39,10 @@ use impls;
39
39
/// brute-force search of 2<sup>128</sup>. A very comprehensive analysis of the
40
40
/// current state of known attacks / weaknesses of HC-128 is given in [4].
41
41
///
42
+ /// The average cycle length is expected to be 2^(1024*32-1) = 2^32767.
43
+ /// We support seeding with a 256-bit array, which matches the 128-bit key
44
+ /// concatenated with a 128-bit IV from the stream cipher.
45
+ ///
42
46
/// ## References
43
47
/// [1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"]
44
48
/// (http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf).
@@ -55,8 +59,7 @@ use impls;
55
59
/// (http://library.isical.ac.in:8080/jspui/bitstream/123456789/6636/1/TH431.pdf).
56
60
///
57
61
/// [5]: Internet Engineering Task Force (Februari 2015),
58
- /// ["Prohibiting RC4 Cipher Suites"]
59
- /// (https://tools.ietf.org/html/rfc7465).
62
+ /// ["Prohibiting RC4 Cipher Suites"](https://tools.ietf.org/html/rfc7465).
60
63
#[ derive( Clone ) ]
61
64
pub struct Hc128Rng {
62
65
state : Hc128 ,
@@ -89,7 +92,7 @@ impl Hc128Rng {
89
92
// Initialize an HC-128 random number generator. The seed has to be
90
93
// 256 bits in length (`[u32; 8]`), matching the 128 bit `key` followed by
91
94
// 128 bit `iv` when HC-128 where to be used as a stream cipher.
92
- pub fn init ( seed : & [ u32 ] ) -> Hc128Rng {
95
+ fn init ( seed : [ u32 ; SEED_WORDS ] ) -> Self {
93
96
#[ inline]
94
97
fn f1 ( x : u32 ) -> u32 {
95
98
x. rotate_right ( 7 ) ^ x. rotate_right ( 18 ) ^ ( x >> 3 )
@@ -129,15 +132,12 @@ impl Hc128Rng {
129
132
let mut state = Hc128Rng {
130
133
state : Hc128 { t : t, counter1024 : 0 } ,
131
134
results : [ 0 ; 16 ] ,
132
- index : 0 ,
135
+ index : 16 , // generate on first use
133
136
} ;
134
137
135
138
// run the cipher 1024 steps
136
139
for _ in 0 ..64 { state. state . sixteen_steps ( ) } ;
137
140
state. state . counter1024 = 0 ;
138
-
139
- // Prepare the first set of results
140
- state. state . update ( & mut state. results ) ;
141
141
state
142
142
}
143
143
}
@@ -400,19 +400,18 @@ impl Rand for Hc128Rng {
400
400
let slice = slice:: from_raw_parts_mut ( ptr, 8 * 4 ) ;
401
401
other. fill_bytes ( slice) ;
402
402
}
403
- Hc128Rng :: init ( & seed)
403
+ Hc128Rng :: init ( seed)
404
404
}
405
405
}
406
406
407
- impl < ' a > SeedableRng < & ' a [ u32 ] > for Hc128Rng {
408
- fn reseed ( & mut self , seed : & ' a [ u32 ] ) {
407
+ impl SeedableRng < [ u32 ; SEED_WORDS ] > for Hc128Rng {
408
+ fn reseed ( & mut self , seed : [ u32 ; SEED_WORDS ] ) {
409
409
* self = Self :: from_seed ( seed) ;
410
410
}
411
411
/// Create an HC-128 random number generator with a seed. The seed has to be
412
412
/// 256 bits in length, matching the 128 bit `key` followed by 128 bit `iv`
413
413
/// when HC-128 where to be used as a stream cipher.
414
- fn from_seed ( seed : & ' a [ u32 ] ) -> Hc128Rng {
415
- assert ! ( seed. len( ) == 8 ) ;
414
+ fn from_seed ( seed : [ u32 ; SEED_WORDS ] ) -> Hc128Rng {
416
415
Hc128Rng :: init ( seed)
417
416
}
418
417
}
@@ -427,7 +426,7 @@ mod test {
427
426
fn test_hc128_true_values_a ( ) {
428
427
let seed = [ 0u32 , 0 , 0 , 0 , // key
429
428
0 , 0 , 0 , 0 ] ; // iv
430
- let mut rng = Hc128Rng :: from_seed ( & seed) ;
429
+ let mut rng = Hc128Rng :: from_seed ( seed) ;
431
430
432
431
let v = ( 0 ..16 ) . map ( |_| rng. next_u32 ( ) ) . collect :: < Vec < _ > > ( ) ;
433
432
assert_eq ! ( v,
@@ -442,7 +441,7 @@ mod test {
442
441
fn test_hc128_true_values_b ( ) {
443
442
let seed = [ 0u32 , 0 , 0 , 0 , // key
444
443
1 , 0 , 0 , 0 ] ; // iv
445
- let mut rng = Hc128Rng :: from_seed ( & seed) ;
444
+ let mut rng = Hc128Rng :: from_seed ( seed) ;
446
445
447
446
let v = ( 0 ..16 ) . map ( |_| rng. next_u32 ( ) ) . collect :: < Vec < _ > > ( ) ;
448
447
assert_eq ! ( v,
@@ -457,7 +456,7 @@ mod test {
457
456
fn test_hc128_true_values_c ( ) {
458
457
let seed = [ 0x55u32 , 0 , 0 , 0 , // key
459
458
0 , 0 , 0 , 0 ] ; // iv
460
- let mut rng = Hc128Rng :: from_seed ( & seed) ;
459
+ let mut rng = Hc128Rng :: from_seed ( seed) ;
461
460
462
461
let v = ( 0 ..16 ) . map ( |_| rng. next_u32 ( ) ) . collect :: < Vec < _ > > ( ) ;
463
462
assert_eq ! ( v,
@@ -471,7 +470,7 @@ mod test {
471
470
fn test_hc128_true_values_u64 ( ) {
472
471
let seed = [ 0u32 , 0 , 0 , 0 , // key
473
472
0 , 0 , 0 , 0 ] ; // iv
474
- let mut rng = Hc128Rng :: from_seed ( & seed) ;
473
+ let mut rng = Hc128Rng :: from_seed ( seed) ;
475
474
476
475
let v = ( 0 ..8 ) . map ( |_| rng. next_u64 ( ) ) . collect :: < Vec < _ > > ( ) ;
477
476
assert_eq ! ( v,
@@ -497,7 +496,7 @@ mod test {
497
496
fn test_hc128_true_values_bytes ( ) {
498
497
let seed = [ 0x55u32 , 0 , 0 , 0 , // key
499
498
0 , 0 , 0 , 0 ] ; // iv
500
- let mut rng = Hc128Rng :: from_seed ( & seed) ;
499
+ let mut rng = Hc128Rng :: from_seed ( seed) ;
501
500
let expected =
502
501
vec ! ( 0x31 , 0xf9 , 0x2a , 0xb0 , 0x32 , 0xf0 , 0x39 , 0x06 ,
503
502
0x7a , 0xa4 , 0xb4 , 0xbc , 0x0b , 0x48 , 0x22 , 0x57 ,
@@ -534,7 +533,7 @@ mod test {
534
533
fn test_hc128_clone ( ) {
535
534
let seed = [ 0x55 , 0 , 0 , 0 , // key
536
535
0 , 0 , 0 , 0 ] ; // iv
537
- let mut rng1 = Hc128Rng :: from_seed ( & seed) ;
536
+ let mut rng1 = Hc128Rng :: from_seed ( seed) ;
538
537
let mut rng2 = rng1. clone ( ) ;
539
538
for _ in 0 ..16 {
540
539
assert_eq ! ( rng1. next_u32( ) , rng2. next_u32( ) ) ;
0 commit comments