rand_isaac/
isaac.rs

1// Copyright 2018 Developers of the Rand project.
2// Copyright 2013-2018 The Rust Project Developers.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! The ISAAC random number generator.
11
12use core::{fmt, slice};
13use core::num::Wrapping as w;
14use rand_core::{RngCore, SeedableRng, Error, le};
15use rand_core::block::{BlockRngCore, BlockRng};
16use isaac_array::IsaacArray;
17
18#[allow(non_camel_case_types)]
19type w32 = w<u32>;
20
21const RAND_SIZE_LEN: usize = 8;
22const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
23
24/// A random number generator that uses the ISAAC algorithm.
25///
26/// ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are
27/// the principal bitwise operations employed. It is the most advanced of a
28/// series of array based random number generator designed by Robert Jenkins
29/// in 1996[^1][^2].
30///
31/// ISAAC is notably fast and produces excellent quality random numbers for
32/// non-cryptographic applications.
33///
34/// In spite of being designed with cryptographic security in mind, ISAAC hasn't
35/// been stringently cryptanalyzed and thus cryptographers do not not
36/// consensually trust it to be secure. When looking for a secure RNG, prefer
37/// [`Hc128Rng`] instead, which, like ISAAC, is an array-based RNG and one of
38/// the stream-ciphers selected the by eSTREAM contest.
39///
40/// In 2006 an improvement to ISAAC was suggested by Jean-Philippe Aumasson,
41/// named ISAAC+[^3]. But because the specification is not complete, because
42/// there is no good implementation, and because the suggested bias may not
43/// exist, it is not implemented here.
44///
45/// ## Overview of the ISAAC algorithm:
46/// (in pseudo-code)
47///
48/// ```text
49/// Input: a, b, c, s[256] // state
50/// Output: r[256]         // results
51///
52/// mix(a,i) = a ^ a << 13   if i = 0 mod 4
53///            a ^ a >>  6   if i = 1 mod 4
54///            a ^ a <<  2   if i = 2 mod 4
55///            a ^ a >> 16   if i = 3 mod 4
56///
57/// c = c + 1
58/// b = b + c
59///
60/// for i in 0..256 {
61///     x = s_[i]
62///     a = f(a,i) + s[i+128 mod 256]
63///     y = a + b + s[x>>2 mod 256]
64///     s[i] = y
65///     b = x + s[y>>10 mod 256]
66///     r[i] = b
67/// }
68/// ```
69///
70/// Numbers are generated in blocks of 256. This means the function above only
71/// runs once every 256 times you ask for a next random number. In all other
72/// circumstances the last element of the results array is returned.
73///
74/// ISAAC therefore needs a lot of memory, relative to other non-crypto RNGs.
75/// 2 * 256 * 4 = 2 kb to hold the state and results.
76///
77/// This implementation uses [`BlockRng`] to implement the [`RngCore`] methods.
78///
79/// ## References
80/// [^1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number generator*](
81///       http://burtleburtle.net/bob/rand/isaacafa.html)
82///
83/// [^2]: Bob Jenkins, [*ISAAC and RC4*](
84///       http://burtleburtle.net/bob/rand/isaac.html)
85///
86/// [^3]: Jean-Philippe Aumasson, [*On the pseudo-random generator ISAAC*](
87///       https://eprint.iacr.org/2006/438)
88///
89/// [`Hc128Rng`]: ../../rand_hc/struct.Hc128Rng.html
90/// [`BlockRng`]: ../../rand_core/block/struct.BlockRng.html
91/// [`RngCore`]: ../../rand_core/trait.RngCore.html
92#[derive(Clone, Debug)]
93#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
94pub struct IsaacRng(BlockRng<IsaacCore>);
95
96impl RngCore for IsaacRng {
97    #[inline(always)]
98    fn next_u32(&mut self) -> u32 {
99        self.0.next_u32()
100    }
101
102    #[inline(always)]
103    fn next_u64(&mut self) -> u64 {
104        self.0.next_u64()
105    }
106
107    fn fill_bytes(&mut self, dest: &mut [u8]) {
108        self.0.fill_bytes(dest)
109    }
110
111    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
112        self.0.try_fill_bytes(dest)
113    }
114}
115
116impl SeedableRng for IsaacRng {
117    type Seed = <IsaacCore as SeedableRng>::Seed;
118
119    fn from_seed(seed: Self::Seed) -> Self {
120        IsaacRng(BlockRng::<IsaacCore>::from_seed(seed))
121    }
122    
123    /// Create an ISAAC random number generator using an `u64` as seed.
124    /// If `seed == 0` this will produce the same stream of random numbers as
125    /// the reference implementation when used unseeded.
126    fn seed_from_u64(seed: u64) -> Self {
127        IsaacRng(BlockRng::<IsaacCore>::seed_from_u64(seed))
128    }
129
130    fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
131        BlockRng::<IsaacCore>::from_rng(rng).map(|rng| IsaacRng(rng))
132    }
133}
134
135impl IsaacRng {
136    /// Create an ISAAC random number generator using an `u64` as seed.
137    /// If `seed == 0` this will produce the same stream of random numbers as
138    /// the reference implementation when used unseeded.
139    #[deprecated(since="0.6.0", note="use SeedableRng::seed_from_u64 instead")]
140    pub fn new_from_u64(seed: u64) -> Self {
141        Self::seed_from_u64(seed)
142    }
143}
144
145/// The core of `IsaacRng`, used with `BlockRng`.
146#[derive(Clone)]
147#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
148pub struct IsaacCore {
149    #[cfg_attr(feature="serde1",serde(with="super::isaac_array::isaac_array_serde"))]
150    mem: [w32; RAND_SIZE],
151    a: w32,
152    b: w32,
153    c: w32,
154}
155
156// Custom Debug implementation that does not expose the internal state
157impl fmt::Debug for IsaacCore {
158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159        write!(f, "IsaacCore {{}}")
160    }
161}
162
163impl BlockRngCore for IsaacCore {
164    type Item = u32;
165    type Results = IsaacArray<Self::Item>;
166
167    /// Refills the output buffer, `results`. See also the pseudocode desciption
168    /// of the algorithm in the [`IsaacRng`] documentation.
169    ///
170    /// Optimisations used (similar to the reference implementation):
171    /// 
172    /// - The loop is unrolled 4 times, once for every constant of mix().
173    /// - The contents of the main loop are moved to a function `rngstep`, to
174    ///   reduce code duplication.
175    /// - We use local variables for a and b, which helps with optimisations.
176    /// - We split the main loop in two, one that operates over 0..128 and one
177    ///   over 128..256. This way we can optimise out the addition and modulus
178    ///   from `s[i+128 mod 256]`.
179    /// - We maintain one index `i` and add `m` or `m2` as base (m2 for the
180    ///   `s[i+128 mod 256]`), relying on the optimizer to turn it into pointer
181    ///   arithmetic.
182    /// - We fill `results` backwards. The reference implementation reads values
183    ///   from `results` in reverse. We read them in the normal direction, to
184    ///   make `fill_bytes` a memcopy. To maintain compatibility we fill in
185    ///   reverse.
186    /// 
187    /// [`IsaacRng`]: struct.IsaacRng.html
188    fn generate(&mut self, results: &mut IsaacArray<Self::Item>) {
189        self.c += w(1);
190        // abbreviations
191        let mut a = self.a;
192        let mut b = self.b + self.c;
193        const MIDPOINT: usize = RAND_SIZE / 2;
194
195        #[inline]
196        fn ind(mem:&[w32; RAND_SIZE], v: w32, amount: usize) -> w32 {
197            let index = (v >> amount).0 as usize % RAND_SIZE;
198            mem[index]
199        }
200
201        #[inline]
202        fn rngstep(mem: &mut [w32; RAND_SIZE],
203                   results: &mut [u32; RAND_SIZE],
204                   mix: w32,
205                   a: &mut w32,
206                   b: &mut w32,
207                   base: usize,
208                   m: usize,
209                   m2: usize) {
210            let x = mem[base + m];
211            *a = mix + mem[base + m2];
212            let y = *a + *b + ind(&mem, x, 2);
213            mem[base + m] = y;
214            *b = x + ind(&mem, y, 2 + RAND_SIZE_LEN);
215            results[RAND_SIZE - 1 - base - m] = (*b).0;
216        }
217
218        let mut m = 0;
219        let mut m2 = MIDPOINT;
220        for i in (0..MIDPOINT/4).map(|i| i * 4) {
221            rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
222            rngstep(&mut self.mem, results, a ^ (a >> 6 ),  &mut a, &mut b, i + 1, m, m2);
223            rngstep(&mut self.mem, results, a ^ (a << 2 ),  &mut a, &mut b, i + 2, m, m2);
224            rngstep(&mut self.mem, results, a ^ (a >> 16),  &mut a, &mut b, i + 3, m, m2);
225        }
226
227        m = MIDPOINT;
228        m2 = 0;
229        for i in (0..MIDPOINT/4).map(|i| i * 4) {
230            rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2);
231            rngstep(&mut self.mem, results, a ^ (a >> 6 ),  &mut a, &mut b, i + 1, m, m2);
232            rngstep(&mut self.mem, results, a ^ (a << 2 ),  &mut a, &mut b, i + 2, m, m2);
233            rngstep(&mut self.mem, results, a ^ (a >> 16),  &mut a, &mut b, i + 3, m, m2);
234        }
235
236        self.a = a;
237        self.b = b;
238    }
239}
240
241impl IsaacCore {
242    /// Create a new ISAAC random number generator.
243    ///
244    /// The author Bob Jenkins describes how to best initialize ISAAC here:
245    /// <https://rt.cpan.org/Public/Bug/Display.html?id=64324>
246    /// The answer is included here just in case:
247    ///
248    /// "No, you don't need a full 8192 bits of seed data. Normal key sizes will
249    /// do fine, and they should have their expected strength (eg a 40-bit key
250    /// will take as much time to brute force as 40-bit keys usually will). You
251    /// could fill the remainder with 0, but set the last array element to the
252    /// length of the key provided (to distinguish keys that differ only by
253    /// different amounts of 0 padding). You do still need to call `randinit()`
254    /// to make sure the initial state isn't uniform-looking."
255    /// "After publishing ISAAC, I wanted to limit the key to half the size of
256    /// `r[]`, and repeat it twice. That would have made it hard to provide a
257    /// key that sets the whole internal state to anything convenient. But I'd
258    /// already published it."
259    ///
260    /// And his answer to the question "For my code, would repeating the key
261    /// over and over to fill 256 integers be a better solution than
262    /// zero-filling, or would they essentially be the same?":
263    /// "If the seed is under 32 bytes, they're essentially the same, otherwise
264    /// repeating the seed would be stronger. randinit() takes a chunk of 32
265    /// bytes, mixes it, and combines that with the next 32 bytes, et cetera.
266    /// Then loops over all the elements the same way a second time."
267    #[inline]
268    fn init(mut mem: [w32; RAND_SIZE], rounds: u32) -> Self {
269        fn mix(a: &mut w32, b: &mut w32, c: &mut w32, d: &mut w32,
270               e: &mut w32, f: &mut w32, g: &mut w32, h: &mut w32) {
271            *a ^= *b << 11; *d += *a; *b += *c;
272            *b ^= *c >> 2;  *e += *b; *c += *d;
273            *c ^= *d << 8;  *f += *c; *d += *e;
274            *d ^= *e >> 16; *g += *d; *e += *f;
275            *e ^= *f << 10; *h += *e; *f += *g;
276            *f ^= *g >> 4;  *a += *f; *g += *h;
277            *g ^= *h << 8;  *b += *g; *h += *a;
278            *h ^= *a >> 9;  *c += *h; *a += *b;
279        }
280
281        // These numbers are the result of initializing a...h with the
282        // fractional part of the golden ratio in binary (0x9e3779b9)
283        // and applying mix() 4 times.
284        let mut a = w(0x1367df5a);
285        let mut b = w(0x95d90059);
286        let mut c = w(0xc3163e4b);
287        let mut d = w(0x0f421ad8);
288        let mut e = w(0xd92a4a78);
289        let mut f = w(0xa51a3c49);
290        let mut g = w(0xc4efea1b);
291        let mut h = w(0x30609119);
292
293        // Normally this should do two passes, to make all of the seed effect
294        // all of `mem`
295        for _ in 0..rounds {
296            for i in (0..RAND_SIZE/8).map(|i| i * 8) {
297                a += mem[i  ]; b += mem[i+1];
298                c += mem[i+2]; d += mem[i+3];
299                e += mem[i+4]; f += mem[i+5];
300                g += mem[i+6]; h += mem[i+7];
301                mix(&mut a, &mut b, &mut c, &mut d,
302                    &mut e, &mut f, &mut g, &mut h);
303                mem[i  ] = a; mem[i+1] = b;
304                mem[i+2] = c; mem[i+3] = d;
305                mem[i+4] = e; mem[i+5] = f;
306                mem[i+6] = g; mem[i+7] = h;
307            }
308        }
309
310        Self { mem, a: w(0), b: w(0), c: w(0) }
311    }
312}
313
314impl SeedableRng for IsaacCore {
315    type Seed = [u8; 32];
316
317    fn from_seed(seed: Self::Seed) -> Self {
318        let mut seed_u32 = [0u32; 8];
319        le::read_u32_into(&seed, &mut seed_u32);
320        // Convert the seed to `Wrapping<u32>` and zero-extend to `RAND_SIZE`.
321        let mut seed_extended = [w(0); RAND_SIZE];
322        for (x, y) in seed_extended.iter_mut().zip(seed_u32.iter()) {
323            *x = w(*y);
324        }
325        Self::init(seed_extended, 2)
326    }
327    
328    /// Create an ISAAC random number generator using an `u64` as seed.
329    /// If `seed == 0` this will produce the same stream of random numbers as
330    /// the reference implementation when used unseeded.
331    fn seed_from_u64(seed: u64) -> Self {
332        let mut key = [w(0); RAND_SIZE];
333        key[0] = w(seed as u32);
334        key[1] = w((seed >> 32) as u32);
335        // Initialize with only one pass.
336        // A second pass does not improve the quality here, because all of the
337        // seed was already available in the first round.
338        // Not doing the second pass has the small advantage that if
339        // `seed == 0` this method produces exactly the same state as the
340        // reference implementation when used unseeded.
341        Self::init(key, 1)
342    }
343
344    fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
345        // Custom `from_rng` implementation that fills a seed with the same size
346        // as the entire state.
347        let mut seed = [w(0u32); RAND_SIZE];
348        unsafe {
349            let ptr = seed.as_mut_ptr() as *mut u8;
350
351            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4);
352            rng.try_fill_bytes(slice)?;
353        }
354        for i in seed.iter_mut() {
355            *i = w(i.0.to_le());
356        }
357
358        Ok(Self::init(seed, 2))
359    }
360}
361
362#[cfg(test)]
363mod test {
364    use rand_core::{RngCore, SeedableRng};
365    use super::IsaacRng;
366
367    #[test]
368    fn test_isaac_construction() {
369        // Test that various construction techniques produce a working RNG.
370        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
371                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
372        let mut rng1 = IsaacRng::from_seed(seed);
373        assert_eq!(rng1.next_u32(), 2869442790);
374
375        let mut rng2 = IsaacRng::from_rng(rng1).unwrap();
376        assert_eq!(rng2.next_u32(), 3094074039);
377    }
378
379    #[test]
380    fn test_isaac_true_values_32() {
381        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
382                     57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
383        let mut rng1 = IsaacRng::from_seed(seed);
384        let mut results = [0u32; 10];
385        for i in results.iter_mut() { *i = rng1.next_u32(); }
386        let expected = [
387            2558573138, 873787463, 263499565, 2103644246, 3595684709,
388            4203127393, 264982119, 2765226902, 2737944514, 3900253796];
389        assert_eq!(results, expected);
390
391        let seed = [57,48,0,0, 50,9,1,0, 49,212,0,0, 148,38,0,0,
392                    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
393        let mut rng2 = IsaacRng::from_seed(seed);
394        // skip forward to the 10000th number
395        for _ in 0..10000 { rng2.next_u32(); }
396
397        for i in results.iter_mut() { *i = rng2.next_u32(); }
398        let expected = [
399            3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
400            1576568959, 3507990155, 179069555, 141456972, 2478885421];
401        assert_eq!(results, expected);
402    }
403
404    #[test]
405    fn test_isaac_true_values_64() {
406        // As above, using little-endian versions of above values
407        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
408                    57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
409        let mut rng = IsaacRng::from_seed(seed);
410        let mut results = [0u64; 5];
411        for i in results.iter_mut() { *i = rng.next_u64(); }
412        let expected = [
413            3752888579798383186, 9035083239252078381,18052294697452424037,
414            11876559110374379111, 16751462502657800130];
415        assert_eq!(results, expected);
416    }
417
418    #[test]
419    fn test_isaac_true_bytes() {
420        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
421                     57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
422        let mut rng = IsaacRng::from_seed(seed);
423        let mut results = [0u8; 32];
424        rng.fill_bytes(&mut results);
425        // Same as first values in test_isaac_true_values as bytes in LE order
426        let expected = [82, 186, 128, 152, 71, 240, 20, 52,
427                        45, 175, 180, 15, 86, 16, 99, 125,
428                        101, 203, 81, 214, 97, 162, 134, 250,
429                        103, 78, 203, 15, 150, 3, 210, 164];
430        assert_eq!(results, expected);
431    }
432
433    #[test]
434    fn test_isaac_new_uninitialized() {
435        // Compare the results from initializing `IsaacRng` with
436        // `seed_from_u64(0)`, to make sure it is the same as the reference
437        // implementation when used uninitialized.
438        // Note: We only test the first 16 integers, not the full 256 of the
439        // first block.
440        let mut rng = IsaacRng::seed_from_u64(0);
441        let mut results = [0u32; 16];
442        for i in results.iter_mut() { *i = rng.next_u32(); }
443        let expected: [u32; 16] = [
444            0x71D71FD2, 0xB54ADAE7, 0xD4788559, 0xC36129FA,
445            0x21DC1EA9, 0x3CB879CA, 0xD83B237F, 0xFA3CE5BD,
446            0x8D048509, 0xD82E9489, 0xDB452848, 0xCA20E846,
447            0x500F972E, 0x0EEFF940, 0x00D6B993, 0xBC12C17F];
448        assert_eq!(results, expected);
449    }
450
451    #[test]
452    fn test_isaac_clone() {
453        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
454                     57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
455        let mut rng1 = IsaacRng::from_seed(seed);
456        let mut rng2 = rng1.clone();
457        for _ in 0..16 {
458            assert_eq!(rng1.next_u32(), rng2.next_u32());
459        }
460    }
461
462    #[test]
463    #[cfg(feature="serde1")]
464    fn test_isaac_serde() {
465        use bincode;
466        use std::io::{BufWriter, BufReader};
467
468        let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
469                     57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
470        let mut rng = IsaacRng::from_seed(seed);
471
472        let buf: Vec<u8> = Vec::new();
473        let mut buf = BufWriter::new(buf);
474        bincode::serialize_into(&mut buf, &rng).expect("Could not serialize");
475
476        let buf = buf.into_inner().unwrap();
477        let mut read = BufReader::new(&buf[..]);
478        let mut deserialized: IsaacRng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
479
480        for _ in 0..300 { // more than the 256 buffered results
481            assert_eq!(rng.next_u32(), deserialized.next_u32());
482        }
483    }
484}