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