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