rand_hc/
hc128.rs

1// Copyright 2018 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! The HC-128 random number generator.
10
11use core::fmt;
12use rand_core::{CryptoRng, RngCore, SeedableRng, Error, le};
13use rand_core::block::{BlockRngCore, BlockRng};
14
15const SEED_WORDS: usize = 8; // 128 bit key followed by 128 bit iv
16
17/// A cryptographically secure random number generator that uses the HC-128
18/// algorithm.
19///
20/// HC-128 is a stream cipher designed by Hongjun Wu[^1], that we use as an
21/// RNG. It is selected as one of the "stream ciphers suitable for widespread
22/// adoption" by eSTREAM[^2].
23///
24/// HC-128 is an array based RNG. In this it is similar to RC-4 and ISAAC before
25/// it, but those have never been proven cryptographically secure (or have even
26/// been significantly compromised, as in the case of RC-4[^5]).
27///
28/// Because HC-128 works with simple indexing into a large array and with a few
29/// operations that parallelize well, it has very good performance. The size of
30/// the array it needs, 4kb, can however be a disadvantage.
31///
32/// This implementation is not based on the version of HC-128 submitted to the
33/// eSTREAM contest, but on a later version by the author with a few small
34/// improvements from December 15, 2009[^3].
35///
36/// HC-128 has no known weaknesses that are easier to exploit than doing a
37/// brute-force search of 2<sup>128</sup>. A very comprehensive analysis of the
38/// current state of known attacks / weaknesses of HC-128 is given in *Some
39/// Results On Analysis And Implementation Of HC-128 Stream Cipher*[^4].
40///
41/// The average cycle length is expected to be
42/// 2<sup>1024*32+10-1</sup> = 2<sup>32777</sup>.
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///
46/// This implementation uses an output buffer of sixteen `u32` words, and uses
47/// [`BlockRng`] to implement the [`RngCore`] methods.
48///
49/// ## References
50/// [^1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"](
51///       http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf).
52///       *The eSTREAM Finalists*, LNCS 4986, pp. 39–47, Springer-Verlag.
53///
54/// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project](
55///       http://www.ecrypt.eu.org/stream/)
56///
57/// [^3]: Hongjun Wu, [Stream Ciphers HC-128 and HC-256](
58///       https://www.ntu.edu.sg/home/wuhj/research/hc/index.html)
59///
60/// [^4]: Shashwat Raizada (January 2015),["Some Results On Analysis And
61///       Implementation Of HC-128 Stream Cipher"](
62///       http://library.isical.ac.in:8080/jspui/bitstream/123456789/6636/1/TH431.pdf).
63///
64/// [^5]: Internet Engineering Task Force (February 2015),
65///       ["Prohibiting RC4 Cipher Suites"](https://tools.ietf.org/html/rfc7465).
66///
67/// [`BlockRng`]: ../rand_core/block/struct.BlockRng.html
68/// [`RngCore`]: ../rand_core/trait.RngCore.html
69#[derive(Clone, Debug)]
70pub struct Hc128Rng(BlockRng<Hc128Core>);
71
72impl RngCore for Hc128Rng {
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    fn fill_bytes(&mut self, dest: &mut [u8]) {
84        self.0.fill_bytes(dest)
85    }
86
87    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
88        self.0.try_fill_bytes(dest)
89    }
90}
91
92impl SeedableRng for Hc128Rng {
93    type Seed = <Hc128Core as SeedableRng>::Seed;
94
95    fn from_seed(seed: Self::Seed) -> Self {
96        Hc128Rng(BlockRng::<Hc128Core>::from_seed(seed))
97    }
98
99    fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
100        BlockRng::<Hc128Core>::from_rng(rng).map(Hc128Rng)
101    }
102}
103
104impl CryptoRng for Hc128Rng {}
105
106/// The core of `Hc128Rng`, used with `BlockRng`.
107#[derive(Clone)]
108pub struct Hc128Core {
109    t: [u32; 1024],
110    counter1024: usize,
111}
112
113// Custom Debug implementation that does not expose the internal state
114impl fmt::Debug for Hc128Core {
115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116        write!(f, "Hc128Core {{}}")
117    }
118}
119
120impl BlockRngCore for Hc128Core {
121    type Item = u32;
122    type Results = [u32; 16];
123
124    fn generate(&mut self, results: &mut Self::Results) {
125        assert!(self.counter1024 % 16 == 0);
126
127        let cc = self.counter1024 % 512;
128        let dd = (cc + 16) % 512;
129        let ee = cc.wrapping_sub(16) % 512;
130
131        if self.counter1024 & 512 == 0 {
132            // P block
133            results[0]  = self.step_p(cc+0,  cc+1,  ee+13, ee+6,  ee+4);
134            results[1]  = self.step_p(cc+1,  cc+2,  ee+14, ee+7,  ee+5);
135            results[2]  = self.step_p(cc+2,  cc+3,  ee+15, ee+8,  ee+6);
136            results[3]  = self.step_p(cc+3,  cc+4,  cc+0,  ee+9,  ee+7);
137            results[4]  = self.step_p(cc+4,  cc+5,  cc+1,  ee+10, ee+8);
138            results[5]  = self.step_p(cc+5,  cc+6,  cc+2,  ee+11, ee+9);
139            results[6]  = self.step_p(cc+6,  cc+7,  cc+3,  ee+12, ee+10);
140            results[7]  = self.step_p(cc+7,  cc+8,  cc+4,  ee+13, ee+11);
141            results[8]  = self.step_p(cc+8,  cc+9,  cc+5,  ee+14, ee+12);
142            results[9]  = self.step_p(cc+9,  cc+10, cc+6,  ee+15, ee+13);
143            results[10] = self.step_p(cc+10, cc+11, cc+7,  cc+0,  ee+14);
144            results[11] = self.step_p(cc+11, cc+12, cc+8,  cc+1,  ee+15);
145            results[12] = self.step_p(cc+12, cc+13, cc+9,  cc+2,  cc+0);
146            results[13] = self.step_p(cc+13, cc+14, cc+10, cc+3,  cc+1);
147            results[14] = self.step_p(cc+14, cc+15, cc+11, cc+4,  cc+2);
148            results[15] = self.step_p(cc+15, dd+0,  cc+12, cc+5,  cc+3);
149        } else {
150            // Q block
151            results[0]  = self.step_q(cc+0,  cc+1,  ee+13, ee+6,  ee+4);
152            results[1]  = self.step_q(cc+1,  cc+2,  ee+14, ee+7,  ee+5);
153            results[2]  = self.step_q(cc+2,  cc+3,  ee+15, ee+8,  ee+6);
154            results[3]  = self.step_q(cc+3,  cc+4,  cc+0,  ee+9,  ee+7);
155            results[4]  = self.step_q(cc+4,  cc+5,  cc+1,  ee+10, ee+8);
156            results[5]  = self.step_q(cc+5,  cc+6,  cc+2,  ee+11, ee+9);
157            results[6]  = self.step_q(cc+6,  cc+7,  cc+3,  ee+12, ee+10);
158            results[7]  = self.step_q(cc+7,  cc+8,  cc+4,  ee+13, ee+11);
159            results[8]  = self.step_q(cc+8,  cc+9,  cc+5,  ee+14, ee+12);
160            results[9]  = self.step_q(cc+9,  cc+10, cc+6,  ee+15, ee+13);
161            results[10] = self.step_q(cc+10, cc+11, cc+7,  cc+0,  ee+14);
162            results[11] = self.step_q(cc+11, cc+12, cc+8,  cc+1,  ee+15);
163            results[12] = self.step_q(cc+12, cc+13, cc+9,  cc+2,  cc+0);
164            results[13] = self.step_q(cc+13, cc+14, cc+10, cc+3,  cc+1);
165            results[14] = self.step_q(cc+14, cc+15, cc+11, cc+4,  cc+2);
166            results[15] = self.step_q(cc+15, dd+0,  cc+12, cc+5,  cc+3);
167        }
168        self.counter1024 = self.counter1024.wrapping_add(16);
169    }
170}
171
172impl Hc128Core {
173    // One step of HC-128, update P and generate 32 bits keystream
174    #[inline(always)]
175    fn step_p(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize)
176         -> u32
177    {
178        let (p, q) = self.t.split_at_mut(512);
179        // FIXME: it would be great if we the bounds checks here could be
180        // optimized out, and we would not need unsafe.
181        // This improves performance by about 7%.
182        unsafe {
183            let temp0 = p.get_unchecked(i511).rotate_right(23);
184            let temp1 = p.get_unchecked(i3).rotate_right(10);
185            let temp2 = p.get_unchecked(i10).rotate_right(8);
186            *p.get_unchecked_mut(i) = p.get_unchecked(i)
187                                       .wrapping_add(temp2)
188                                       .wrapping_add(temp0 ^ temp1);
189            let temp3 = {
190                // The h1 function in HC-128
191                let a = *p.get_unchecked(i12) as u8;
192                let c = (p.get_unchecked(i12) >> 16) as u8;
193                q[a as usize].wrapping_add(q[256 + c as usize])
194            };
195            temp3 ^ p.get_unchecked(i)
196        }
197    }
198
199    // One step of HC-128, update Q and generate 32 bits keystream
200    // Similar to `step_p`, but `p` and `q` are swapped, and the rotates are to
201    // the left instead of to the right.
202    #[inline(always)]
203    fn step_q(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize)
204         -> u32
205    {
206        let (p, q) = self.t.split_at_mut(512);
207        unsafe {
208            let temp0 = q.get_unchecked(i511).rotate_left(23);
209            let temp1 = q.get_unchecked(i3).rotate_left(10);
210            let temp2 = q.get_unchecked(i10).rotate_left(8);
211            *q.get_unchecked_mut(i) = q.get_unchecked(i)
212                                       .wrapping_add(temp2)
213                                       .wrapping_add(temp0 ^ temp1);
214            let temp3 = {
215                // The h2 function in HC-128
216                let a = *q.get_unchecked(i12) as u8;
217                let c = (q.get_unchecked(i12) >> 16) as u8;
218                p[a as usize].wrapping_add(p[256 + c as usize])
219            };
220            temp3 ^ q.get_unchecked(i)
221        }
222    }
223
224    fn sixteen_steps(&mut self) {
225        assert!(self.counter1024 % 16 == 0);
226
227        let cc = self.counter1024 % 512;
228        let dd = (cc + 16) % 512;
229        let ee = cc.wrapping_sub(16) % 512;
230
231        if self.counter1024 < 512 {
232            // P block
233            self.t[cc+0]  = self.step_p(cc+0,  cc+1,  ee+13, ee+6,  ee+4);
234            self.t[cc+1]  = self.step_p(cc+1,  cc+2,  ee+14, ee+7,  ee+5);
235            self.t[cc+2]  = self.step_p(cc+2,  cc+3,  ee+15, ee+8,  ee+6);
236            self.t[cc+3]  = self.step_p(cc+3,  cc+4,  cc+0,  ee+9,  ee+7);
237            self.t[cc+4]  = self.step_p(cc+4,  cc+5,  cc+1,  ee+10, ee+8);
238            self.t[cc+5]  = self.step_p(cc+5,  cc+6,  cc+2,  ee+11, ee+9);
239            self.t[cc+6]  = self.step_p(cc+6,  cc+7,  cc+3,  ee+12, ee+10);
240            self.t[cc+7]  = self.step_p(cc+7,  cc+8,  cc+4,  ee+13, ee+11);
241            self.t[cc+8]  = self.step_p(cc+8,  cc+9,  cc+5,  ee+14, ee+12);
242            self.t[cc+9]  = self.step_p(cc+9,  cc+10, cc+6,  ee+15, ee+13);
243            self.t[cc+10] = self.step_p(cc+10, cc+11, cc+7,  cc+0,  ee+14);
244            self.t[cc+11] = self.step_p(cc+11, cc+12, cc+8,  cc+1,  ee+15);
245            self.t[cc+12] = self.step_p(cc+12, cc+13, cc+9,  cc+2,  cc+0);
246            self.t[cc+13] = self.step_p(cc+13, cc+14, cc+10, cc+3,  cc+1);
247            self.t[cc+14] = self.step_p(cc+14, cc+15, cc+11, cc+4,  cc+2);
248            self.t[cc+15] = self.step_p(cc+15, dd+0,  cc+12, cc+5,  cc+3);
249        } else {
250            // Q block
251            self.t[cc+512+0]  = self.step_q(cc+0,  cc+1,  ee+13, ee+6,  ee+4);
252            self.t[cc+512+1]  = self.step_q(cc+1,  cc+2,  ee+14, ee+7,  ee+5);
253            self.t[cc+512+2]  = self.step_q(cc+2,  cc+3,  ee+15, ee+8,  ee+6);
254            self.t[cc+512+3]  = self.step_q(cc+3,  cc+4,  cc+0,  ee+9,  ee+7);
255            self.t[cc+512+4]  = self.step_q(cc+4,  cc+5,  cc+1,  ee+10, ee+8);
256            self.t[cc+512+5]  = self.step_q(cc+5,  cc+6,  cc+2,  ee+11, ee+9);
257            self.t[cc+512+6]  = self.step_q(cc+6,  cc+7,  cc+3,  ee+12, ee+10);
258            self.t[cc+512+7]  = self.step_q(cc+7,  cc+8,  cc+4,  ee+13, ee+11);
259            self.t[cc+512+8]  = self.step_q(cc+8,  cc+9,  cc+5,  ee+14, ee+12);
260            self.t[cc+512+9]  = self.step_q(cc+9,  cc+10, cc+6,  ee+15, ee+13);
261            self.t[cc+512+10] = self.step_q(cc+10, cc+11, cc+7,  cc+0,  ee+14);
262            self.t[cc+512+11] = self.step_q(cc+11, cc+12, cc+8,  cc+1,  ee+15);
263            self.t[cc+512+12] = self.step_q(cc+12, cc+13, cc+9,  cc+2,  cc+0);
264            self.t[cc+512+13] = self.step_q(cc+13, cc+14, cc+10, cc+3,  cc+1);
265            self.t[cc+512+14] = self.step_q(cc+14, cc+15, cc+11, cc+4,  cc+2);
266            self.t[cc+512+15] = self.step_q(cc+15, dd+0,  cc+12, cc+5,  cc+3);
267        }
268        self.counter1024 += 16;
269    }
270
271    // Initialize an HC-128 random number generator. The seed has to be
272    // 256 bits in length (`[u32; 8]`), matching the 128 bit `key` followed by
273    // 128 bit `iv` when HC-128 where to be used as a stream cipher.
274    fn init(seed: [u32; SEED_WORDS]) -> Self {
275        #[inline]
276        fn f1(x: u32) -> u32 {
277            x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3)
278        }
279
280        #[inline]
281        fn f2(x: u32) -> u32 {
282            x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10)
283        }
284
285        let mut t = [0u32; 1024];
286
287        // Expand the key and iv into P and Q
288        let (key, iv) = seed.split_at(4);
289        t[..4].copy_from_slice(key);
290        t[4..8].copy_from_slice(key);
291        t[8..12].copy_from_slice(iv);
292        t[12..16].copy_from_slice(iv);
293
294        // Generate the 256 intermediate values W[16] ... W[256+16-1], and
295        // copy the last 16 generated values to the start op P.
296        for i in 16..256+16 {
297            t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15]))
298                   .wrapping_add(t[i-16]).wrapping_add(i as u32);
299        }
300        {
301            let (p1, p2) = t.split_at_mut(256);
302            p1[0..16].copy_from_slice(&p2[0..16]);
303        }
304
305        // Generate both the P and Q tables
306        for i in 16..1024 {
307            t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15]))
308                   .wrapping_add(t[i-16]).wrapping_add(256 + i as u32);
309        }
310
311        let mut core = Self { t, counter1024: 0 };
312
313        // run the cipher 1024 steps
314        for _ in 0..64 { core.sixteen_steps() };
315        core.counter1024 = 0;
316        core
317    }
318}
319
320impl SeedableRng for Hc128Core {
321    type Seed = [u8; SEED_WORDS*4];
322
323    /// Create an HC-128 random number generator with a seed. The seed has to be
324    /// 256 bits in length, matching the 128 bit `key` followed by 128 bit `iv`
325    /// when HC-128 where to be used as a stream cipher.
326    fn from_seed(seed: Self::Seed) -> Self {
327        let mut seed_u32 = [0u32; SEED_WORDS];
328        le::read_u32_into(&seed, &mut seed_u32);
329        Self::init(seed_u32)
330    }
331}
332
333impl CryptoRng for Hc128Core {}
334
335#[cfg(test)]
336mod test {
337    use ::rand_core::{RngCore, SeedableRng};
338    use super::Hc128Rng;
339
340    #[test]
341    // Test vector 1 from the paper "The Stream Cipher HC-128"
342    fn test_hc128_true_values_a() {
343        let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
344                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
345        let mut rng = Hc128Rng::from_seed(seed);
346
347        let mut results = [0u32; 16];
348        for i in results.iter_mut() { *i = rng.next_u32(); }
349        let expected = [0x73150082, 0x3bfd03a0, 0xfb2fd77f, 0xaa63af0e,
350                        0xde122fc6, 0xa7dc29b6, 0x62a68527, 0x8b75ec68,
351                        0x9036db1e, 0x81896005, 0x00ade078, 0x491fbf9a,
352                        0x1cdc3013, 0x6c3d6e24, 0x90f664b2, 0x9cd57102];
353        assert_eq!(results, expected);
354    }
355
356    #[test]
357    // Test vector 2 from the paper "The Stream Cipher HC-128"
358    fn test_hc128_true_values_b() {
359        let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
360                    1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
361        let mut rng = Hc128Rng::from_seed(seed);
362
363        let mut results = [0u32; 16];
364        for i in results.iter_mut() { *i = rng.next_u32(); }
365        let expected = [0xc01893d5, 0xb7dbe958, 0x8f65ec98, 0x64176604,
366                        0x36fc6724, 0xc82c6eec, 0x1b1c38a7, 0xc9b42a95,
367                        0x323ef123, 0x0a6a908b, 0xce757b68, 0x9f14f7bb,
368                        0xe4cde011, 0xaeb5173f, 0x89608c94, 0xb5cf46ca];
369        assert_eq!(results, expected);
370    }
371
372    #[test]
373    // Test vector 3 from the paper "The Stream Cipher HC-128"
374    fn test_hc128_true_values_c() {
375        let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
376                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
377        let mut rng = Hc128Rng::from_seed(seed);
378
379        let mut results = [0u32; 16];
380        for i in results.iter_mut() { *i = rng.next_u32(); }
381        let expected = [0x518251a4, 0x04b4930a, 0xb02af931, 0x0639f032,
382                        0xbcb4a47a, 0x5722480b, 0x2bf99f72, 0xcdc0e566,
383                        0x310f0c56, 0xd3cc83e8, 0x663db8ef, 0x62dfe07f,
384                        0x593e1790, 0xc5ceaa9c, 0xab03806f, 0xc9a6e5a0];
385        assert_eq!(results, expected);
386    }
387
388    #[test]
389    fn test_hc128_true_values_u64() {
390        let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
391                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
392        let mut rng = Hc128Rng::from_seed(seed);
393
394        let mut results = [0u64; 8];
395        for i in results.iter_mut() { *i = rng.next_u64(); }
396        let expected = [0x3bfd03a073150082, 0xaa63af0efb2fd77f,
397                        0xa7dc29b6de122fc6, 0x8b75ec6862a68527,
398                        0x818960059036db1e, 0x491fbf9a00ade078,
399                        0x6c3d6e241cdc3013, 0x9cd5710290f664b2];
400        assert_eq!(results, expected);
401
402        // The RNG operates in a P block of 512 results and next a Q block.
403        // After skipping 2*800 u32 results we end up somewhere in the Q block
404        // of the second round
405        for _ in 0..800 { rng.next_u64(); }
406
407        for i in results.iter_mut() { *i = rng.next_u64(); }
408        let expected = [0xd8c4d6ca84d0fc10, 0xf16a5d91dc66e8e7,
409                        0xd800de5bc37a8653, 0x7bae1f88c0dfbb4c,
410                        0x3bfe1f374e6d4d14, 0x424b55676be3fa06,
411                        0xe3a1e8758cbff579, 0x417f7198c5652bcd];
412        assert_eq!(results, expected);
413    }
414
415    #[test]
416    fn test_hc128_true_values_bytes() {
417        let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
418                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
419        let mut rng = Hc128Rng::from_seed(seed);
420        let expected = [0x31, 0xf9, 0x2a, 0xb0, 0x32, 0xf0, 0x39, 0x06,
421                 0x7a, 0xa4, 0xb4, 0xbc, 0x0b, 0x48, 0x22, 0x57,
422                 0x72, 0x9f, 0xf9, 0x2b, 0x66, 0xe5, 0xc0, 0xcd,
423                 0x56, 0x0c, 0x0f, 0x31, 0xe8, 0x83, 0xcc, 0xd3,
424                 0xef, 0xb8, 0x3d, 0x66, 0x7f, 0xe0, 0xdf, 0x62,
425                 0x90, 0x17, 0x3e, 0x59, 0x9c, 0xaa, 0xce, 0xc5,
426                 0x6f, 0x80, 0x03, 0xab, 0xa0, 0xe5, 0xa6, 0xc9,
427                 0x60, 0x95, 0x84, 0x7a, 0xa5, 0x68, 0x5a, 0x84,
428                 0xea, 0xd5, 0xf3, 0xea, 0x73, 0xa9, 0xad, 0x01,
429                 0x79, 0x7d, 0xbe, 0x9f, 0xea, 0xe3, 0xf9, 0x74,
430                 0x0e, 0xda, 0x2f, 0xa0, 0xe4, 0x7b, 0x4b, 0x1b,
431                 0xdd, 0x17, 0x69, 0x4a, 0xfe, 0x9f, 0x56, 0x95,
432                 0xad, 0x83, 0x6b, 0x9d, 0x60, 0xa1, 0x99, 0x96,
433                 0x90, 0x00, 0x66, 0x7f, 0xfa, 0x7e, 0x65, 0xe9,
434                 0xac, 0x8b, 0x92, 0x34, 0x77, 0xb4, 0x23, 0xd0,
435                 0xb9, 0xab, 0xb1, 0x47, 0x7d, 0x4a, 0x13, 0x0a];
436
437        // Pick a somewhat large buffer so we can test filling with the
438        // remainder from `state.results`, directly filling the buffer, and
439        // filling the remainder of the buffer.
440        let mut buffer = [0u8; 16*4*2];
441        // Consume a value so that we have a remainder.
442        assert!(rng.next_u64() == 0x04b4930a518251a4);
443        rng.fill_bytes(&mut buffer);
444
445        // [u8; 128] doesn't implement PartialEq
446        assert_eq!(buffer.len(), expected.len());
447        for (b, e) in buffer.iter().zip(expected.iter()) {
448            assert_eq!(b, e);
449        }
450    }
451
452    #[test]
453    fn test_hc128_clone() {
454        let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key
455                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv
456        let mut rng1 = Hc128Rng::from_seed(seed);
457        let mut rng2 = rng1.clone();
458        for _ in 0..16 {
459            assert_eq!(rng1.next_u32(), rng2.next_u32());
460        }
461    }
462}