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