diff options
Diffstat (limited to 'rand/src/prng')
| -rw-r--r-- | rand/src/prng/chacha.rs | 321 | ||||
| -rw-r--r-- | rand/src/prng/isaac.rs | 328 | ||||
| -rw-r--r-- | rand/src/prng/isaac64.rs | 340 | ||||
| -rw-r--r-- | rand/src/prng/mod.rs | 74 | ||||
| -rw-r--r-- | rand/src/prng/xorshift.rs | 101 | 
5 files changed, 30 insertions, 1134 deletions
| diff --git a/rand/src/prng/chacha.rs b/rand/src/prng/chacha.rs deleted file mode 100644 index a73e8e7..0000000 --- a/rand/src/prng/chacha.rs +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The ChaCha random number generator. - -use core::num::Wrapping as w; -use {Rng, SeedableRng, Rand}; - -#[allow(bad_style)] -type w32 = w<u32>; - -const KEY_WORDS    : usize =  8; // 8 words for the 256-bit key -const STATE_WORDS  : usize = 16; -const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of this writing - -/// A random number generator that uses the ChaCha20 algorithm [1]. -/// -/// The ChaCha algorithm is widely accepted as suitable for -/// cryptographic purposes, but this implementation has not been -/// verified as such. Prefer a generator like `OsRng` that defers to -/// the operating system for cases that need high security. -/// -/// [1]: D. J. Bernstein, [*ChaCha, a variant of -/// Salsa20*](http://cr.yp.to/chacha.html) -#[derive(Copy, Clone, Debug)] -pub struct ChaChaRng { -    buffer:  [w32; STATE_WORDS], // Internal buffer of output -    state:   [w32; STATE_WORDS], // Initial state -    index:   usize,                 // Index into state -} - -static EMPTY: ChaChaRng = ChaChaRng { -    buffer:  [w(0); STATE_WORDS], -    state:   [w(0); STATE_WORDS], -    index:   STATE_WORDS -}; - - -macro_rules! quarter_round{ -    ($a: expr, $b: expr, $c: expr, $d: expr) => {{ -        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left(16)); -        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left(12)); -        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left( 8)); -        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left( 7)); -    }} -} - -macro_rules! double_round{ -    ($x: expr) => {{ -        // Column round -        quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]); -        quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]); -        quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]); -        quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]); -        // Diagonal round -        quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]); -        quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]); -        quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]); -        quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]); -    }} -} - -#[inline] -fn core(output: &mut [w32; STATE_WORDS], input: &[w32; STATE_WORDS]) { -    *output = *input; - -    for _ in 0..CHACHA_ROUNDS / 2 { -        double_round!(output); -    } - -    for i in 0..STATE_WORDS { -        output[i] = output[i] + input[i]; -    } -} - -impl ChaChaRng { - -    /// Create an ChaCha random number generator using the default -    /// fixed key of 8 zero words. -    /// -    /// # Examples -    /// -    /// ```rust -    /// use rand::{Rng, ChaChaRng}; -    /// -    /// let mut ra = ChaChaRng::new_unseeded(); -    /// println!("{:?}", ra.next_u32()); -    /// println!("{:?}", ra.next_u32()); -    /// ``` -    /// -    /// Since this equivalent to a RNG with a fixed seed, repeated executions -    /// of an unseeded RNG will produce the same result. This code sample will -    /// consistently produce: -    /// -    /// - 2917185654 -    /// - 2419978656 -    pub fn new_unseeded() -> ChaChaRng { -        let mut rng = EMPTY; -        rng.init(&[0; KEY_WORDS]); -        rng -    } - -    /// Sets the internal 128-bit ChaCha counter to -    /// a user-provided value. This permits jumping -    /// arbitrarily ahead (or backwards) in the pseudorandom stream. -    /// -    /// Since the nonce words are used to extend the counter to 128 bits, -    /// users wishing to obtain the conventional ChaCha pseudorandom stream -    /// associated with a particular nonce can call this function with -    /// arguments `0, desired_nonce`. -    /// -    /// # Examples -    /// -    /// ```rust -    /// use rand::{Rng, ChaChaRng}; -    /// -    /// let mut ra = ChaChaRng::new_unseeded(); -    /// ra.set_counter(0u64, 1234567890u64); -    /// println!("{:?}", ra.next_u32()); -    /// println!("{:?}", ra.next_u32()); -    /// ``` -    pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) { -        self.state[12] = w((counter_low >>  0) as u32); -        self.state[13] = w((counter_low >> 32) as u32); -        self.state[14] = w((counter_high >>  0) as u32); -        self.state[15] = w((counter_high >> 32) as u32); -        self.index = STATE_WORDS; // force recomputation -    } - -    /// Initializes `self.state` with the appropriate key and constants -    /// -    /// We deviate slightly from the ChaCha specification regarding -    /// the nonce, which is used to extend the counter to 128 bits. -    /// This is provably as strong as the original cipher, though, -    /// since any distinguishing attack on our variant also works -    /// against ChaCha with a chosen-nonce. See the XSalsa20 [1] -    /// security proof for a more involved example of this. -    /// -    /// The modified word layout is: -    /// ```text -    /// constant constant constant constant -    /// key      key      key      key -    /// key      key      key      key -    /// counter  counter  counter  counter -    /// ``` -    /// [1]: Daniel J. Bernstein. [*Extending the Salsa20 -    /// nonce.*](http://cr.yp.to/papers.html#xsalsa) -    fn init(&mut self, key: &[u32; KEY_WORDS]) { -        self.state[0] = w(0x61707865); -        self.state[1] = w(0x3320646E); -        self.state[2] = w(0x79622D32); -        self.state[3] = w(0x6B206574); - -        for i in 0..KEY_WORDS { -            self.state[4+i] = w(key[i]); -        } - -        self.state[12] = w(0); -        self.state[13] = w(0); -        self.state[14] = w(0); -        self.state[15] = w(0); - -        self.index = STATE_WORDS; -    } - -    /// Refill the internal output buffer (`self.buffer`) -    fn update(&mut self) { -        core(&mut self.buffer, &self.state); -        self.index = 0; -        // update 128-bit counter -        self.state[12] = self.state[12] + w(1); -        if self.state[12] != w(0) { return }; -        self.state[13] = self.state[13] + w(1); -        if self.state[13] != w(0) { return }; -        self.state[14] = self.state[14] + w(1); -        if self.state[14] != w(0) { return }; -        self.state[15] = self.state[15] + w(1); -    } -} - -impl Rng for ChaChaRng { -    #[inline] -    fn next_u32(&mut self) -> u32 { -        if self.index == STATE_WORDS { -            self.update(); -        } - -        let value = self.buffer[self.index % STATE_WORDS]; -        self.index += 1; -        value.0 -    } -} - -impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { - -    fn reseed(&mut self, seed: &'a [u32]) { -        // reset state -        self.init(&[0u32; KEY_WORDS]); -        // set key in place -        let key = &mut self.state[4 .. 4+KEY_WORDS]; -        for (k, s) in key.iter_mut().zip(seed.iter()) { -            *k = w(*s); -        } -    } - -    /// Create a ChaCha generator from a seed, -    /// obtained from a variable-length u32 array. -    /// Only up to 8 words are used; if less than 8 -    /// words are used, the remaining are set to zero. -    fn from_seed(seed: &'a [u32]) -> ChaChaRng { -        let mut rng = EMPTY; -        rng.reseed(seed); -        rng -    } -} - -impl Rand for ChaChaRng { -    fn rand<R: Rng>(other: &mut R) -> ChaChaRng { -        let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS]; -        for word in key.iter_mut() { -            *word = other.gen(); -        } -        SeedableRng::from_seed(&key[..]) -    } -} - - -#[cfg(test)] -mod test { -    use {Rng, SeedableRng}; -    use super::ChaChaRng; - -    #[test] -    fn test_rng_rand_seeded() { -        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>(); -        let mut ra: ChaChaRng = SeedableRng::from_seed(&s[..]); -        let mut rb: ChaChaRng = SeedableRng::from_seed(&s[..]); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_seeded() { -        let seed : &[_] = &[0,1,2,3,4,5,6,7]; -        let mut ra: ChaChaRng = SeedableRng::from_seed(seed); -        let mut rb: ChaChaRng = SeedableRng::from_seed(seed); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_reseed() { -        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>(); -        let mut r: ChaChaRng = SeedableRng::from_seed(&s[..]); -        let string1: String = r.gen_ascii_chars().take(100).collect(); - -        r.reseed(&s); - -        let string2: String = r.gen_ascii_chars().take(100).collect(); -        assert_eq!(string1, string2); -    } - -    #[test] -    fn test_rng_true_values() { -        // Test vectors 1 and 2 from -        // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 -        let seed : &[_] = &[0u32; 8]; -        let mut ra: ChaChaRng = SeedableRng::from_seed(seed); - -        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, -                        0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b, -                        0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, -                        0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2)); - -        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, -                        0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32, -                        0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, -                        0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b)); - - -        let seed : &[_] = &[0,1,2,3,4,5,6,7]; -        let mut ra: ChaChaRng = SeedableRng::from_seed(seed); - -        // Store the 17*i-th 32-bit word, -        // i.e., the i-th word of the i-th 16-word block -        let mut v : Vec<u32> = Vec::new(); -        for _ in 0..16 { -            v.push(ra.next_u32()); -            for _ in 0..16 { -                ra.next_u32(); -            } -        } - -        assert_eq!(v, -                   vec!(0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, -                        0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384, -                        0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, -                        0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4)); -    } - -    #[test] -    fn test_rng_clone() { -        let seed : &[_] = &[0u32; 8]; -        let mut rng: ChaChaRng = SeedableRng::from_seed(seed); -        let mut clone = rng.clone(); -        for _ in 0..16 { -            assert_eq!(rng.next_u64(), clone.next_u64()); -        } -    } -} diff --git a/rand/src/prng/isaac.rs b/rand/src/prng/isaac.rs deleted file mode 100644 index cf5eb67..0000000 --- a/rand/src/prng/isaac.rs +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The ISAAC random number generator. - -#![allow(non_camel_case_types)] - -use core::slice; -use core::iter::repeat; -use core::num::Wrapping as w; -use core::fmt; - -use {Rng, SeedableRng, Rand}; - -#[allow(bad_style)] -type w32 = w<u32>; - -const RAND_SIZE_LEN: usize = 8; -const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN; -const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN; - -/// A random number generator that uses the ISAAC algorithm[1]. -/// -/// The ISAAC algorithm is generally accepted as suitable for -/// cryptographic purposes, but this implementation has not be -/// verified as such. Prefer a generator like `OsRng` that defers to -/// the operating system for cases that need high security. -/// -/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number -/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html) -#[derive(Copy)] -pub struct IsaacRng { -    cnt: u32, -    rsl: [w32; RAND_SIZE_USIZE], -    mem: [w32; RAND_SIZE_USIZE], -    a: w32, -    b: w32, -    c: w32, -} - -static EMPTY: IsaacRng = IsaacRng { -    cnt: 0, -    rsl: [w(0); RAND_SIZE_USIZE], -    mem: [w(0); RAND_SIZE_USIZE], -    a: w(0), b: w(0), c: w(0), -}; - -impl IsaacRng { - -    /// Create an ISAAC random number generator using the default -    /// fixed seed. -    pub fn new_unseeded() -> IsaacRng { -        let mut rng = EMPTY; -        rng.init(false); -        rng -    } - -    /// Initialises `self`. If `use_rsl` is true, then use the current value -    /// of `rsl` as a seed, otherwise construct one algorithmically (not -    /// randomly). -    fn init(&mut self, use_rsl: bool) { -        let mut a = w(0x9e3779b9); -        let mut b = a; -        let mut c = a; -        let mut d = a; -        let mut e = a; -        let mut f = a; -        let mut g = a; -        let mut h = a; - -        macro_rules! mix { -            () => {{ -                a=a^(b<<11); d=d+a; b=b+c; -                b=b^(c>>2);  e=e+b; c=c+d; -                c=c^(d<<8);  f=f+c; d=d+e; -                d=d^(e>>16); g=g+d; e=e+f; -                e=e^(f<<10); h=h+e; f=f+g; -                f=f^(g>>4);  a=a+f; g=g+h; -                g=g^(h<<8);  b=b+g; h=h+a; -                h=h^(a>>9);  c=c+h; a=a+b; -            }} -        } - -        for _ in 0..4 { -            mix!(); -        } - -        if use_rsl { -            macro_rules! memloop { -                ($arr:expr) => {{ -                    for i in (0..RAND_SIZE_USIZE/8).map(|i| i * 8) { -                        a=a+$arr[i  ]; b=b+$arr[i+1]; -                        c=c+$arr[i+2]; d=d+$arr[i+3]; -                        e=e+$arr[i+4]; f=f+$arr[i+5]; -                        g=g+$arr[i+6]; h=h+$arr[i+7]; -                        mix!(); -                        self.mem[i  ]=a; self.mem[i+1]=b; -                        self.mem[i+2]=c; self.mem[i+3]=d; -                        self.mem[i+4]=e; self.mem[i+5]=f; -                        self.mem[i+6]=g; self.mem[i+7]=h; -                    } -                }} -            } - -            memloop!(self.rsl); -            memloop!(self.mem); -        } else { -            for i in (0..RAND_SIZE_USIZE/8).map(|i| i * 8) { -                mix!(); -                self.mem[i  ]=a; self.mem[i+1]=b; -                self.mem[i+2]=c; self.mem[i+3]=d; -                self.mem[i+4]=e; self.mem[i+5]=f; -                self.mem[i+6]=g; self.mem[i+7]=h; -            } -        } - -        self.isaac(); -    } - -    /// Refills the output buffer (`self.rsl`) -    #[inline] -    fn isaac(&mut self) { -        self.c = self.c + w(1); -        // abbreviations -        let mut a = self.a; -        let mut b = self.b + self.c; - -        const MIDPOINT: usize = RAND_SIZE_USIZE / 2; - -        macro_rules! ind { -            ($x:expr) => ( self.mem[($x >> 2usize).0 as usize & (RAND_SIZE_USIZE - 1)] ) -        } - -        let r = [(0, MIDPOINT), (MIDPOINT, 0)]; -        for &(mr_offset, m2_offset) in r.iter() { - -            macro_rules! rngstepp { -                ($j:expr, $shift:expr) => {{ -                    let base = $j; -                    let mix = a << $shift; - -                    let x = self.mem[base  + mr_offset]; -                    a = (a ^ mix) + self.mem[base + m2_offset]; -                    let y = ind!(x) + a + b; -                    self.mem[base + mr_offset] = y; - -                    b = ind!(y >> RAND_SIZE_LEN) + x; -                    self.rsl[base + mr_offset] = b; -                }} -            } - -            macro_rules! rngstepn { -                ($j:expr, $shift:expr) => {{ -                    let base = $j; -                    let mix = a >> $shift; - -                    let x = self.mem[base  + mr_offset]; -                    a = (a ^ mix) + self.mem[base + m2_offset]; -                    let y = ind!(x) + a + b; -                    self.mem[base + mr_offset] = y; - -                    b = ind!(y >> RAND_SIZE_LEN) + x; -                    self.rsl[base + mr_offset] = b; -                }} -            } - -            for i in (0..MIDPOINT/4).map(|i| i * 4) { -                rngstepp!(i + 0, 13); -                rngstepn!(i + 1, 6); -                rngstepp!(i + 2, 2); -                rngstepn!(i + 3, 16); -            } -        } - -        self.a = a; -        self.b = b; -        self.cnt = RAND_SIZE; -    } -} - -// Cannot be derived because [u32; 256] does not implement Clone -impl Clone for IsaacRng { -    fn clone(&self) -> IsaacRng { -        *self -    } -} - -impl Rng for IsaacRng { -    #[inline] -    fn next_u32(&mut self) -> u32 { -        if self.cnt == 0 { -            // make some more numbers -            self.isaac(); -        } -        self.cnt -= 1; - -        // self.cnt is at most RAND_SIZE, but that is before the -        // subtraction above. We want to index without bounds -        // checking, but this could lead to incorrect code if someone -        // misrefactors, so we check, sometimes. -        // -        // (Changes here should be reflected in Isaac64Rng.next_u64.) -        debug_assert!(self.cnt < RAND_SIZE); - -        // (the % is cheaply telling the optimiser that we're always -        // in bounds, without unsafe. NB. this is a power of two, so -        // it optimises to a bitwise mask). -        self.rsl[(self.cnt % RAND_SIZE) as usize].0 -    } -} - -impl<'a> SeedableRng<&'a [u32]> for IsaacRng { -    fn reseed(&mut self, seed: &'a [u32]) { -        // make the seed into [seed[0], seed[1], ..., seed[seed.len() -        // - 1], 0, 0, ...], to fill rng.rsl. -        let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u32)); - -        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) { -            *rsl_elem = w(seed_elem); -        } -        self.cnt = 0; -        self.a = w(0); -        self.b = w(0); -        self.c = w(0); - -        self.init(true); -    } - -    /// Create an ISAAC random number generator with a seed. This can -    /// be any length, although the maximum number of elements used is -    /// 256 and any more will be silently ignored. A generator -    /// constructed with a given seed will generate the same sequence -    /// of values as all other generators constructed with that seed. -    fn from_seed(seed: &'a [u32]) -> IsaacRng { -        let mut rng = EMPTY; -        rng.reseed(seed); -        rng -    } -} - -impl Rand for IsaacRng { -    fn rand<R: Rng>(other: &mut R) -> IsaacRng { -        let mut ret = EMPTY; -        unsafe { -            let ptr = ret.rsl.as_mut_ptr() as *mut u8; - -            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_USIZE * 4); -            other.fill_bytes(slice); -        } -        ret.cnt = 0; -        ret.a = w(0); -        ret.b = w(0); -        ret.c = w(0); - -        ret.init(true); -        return ret; -    } -} - -impl fmt::Debug for IsaacRng { -    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -        write!(f, "IsaacRng {{}}") -    } -} - -#[cfg(test)] -mod test { -    use {Rng, SeedableRng}; -    use super::IsaacRng; - -    #[test] -    fn test_rng_32_rand_seeded() { -        let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>(); -        let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]); -        let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_32_seeded() { -        let seed: &[_] = &[1, 23, 456, 7890, 12345]; -        let mut ra: IsaacRng = SeedableRng::from_seed(seed); -        let mut rb: IsaacRng = SeedableRng::from_seed(seed); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_32_reseed() { -        let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>(); -        let mut r: IsaacRng = SeedableRng::from_seed(&s[..]); -        let string1: String = r.gen_ascii_chars().take(100).collect(); - -        r.reseed(&s[..]); - -        let string2: String = r.gen_ascii_chars().take(100).collect(); -        assert_eq!(string1, string2); -    } - -    #[test] -    fn test_rng_32_true_values() { -        let seed: &[_] = &[1, 23, 456, 7890, 12345]; -        let mut ra: IsaacRng = SeedableRng::from_seed(seed); -        // Regression test that isaac is actually using the above vector -        let v = (0..10).map(|_| ra.next_u32()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709, -                        4203127393, 264982119, 2765226902, 2737944514, 3900253796)); - -        let seed: &[_] = &[12345, 67890, 54321, 9876]; -        let mut rb: IsaacRng = SeedableRng::from_seed(seed); -        // skip forward to the 10000th number -        for _ in 0..10000 { rb.next_u32(); } - -        let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(3676831399, 3183332890, 2834741178, 3854698763, 2717568474, -                        1576568959, 3507990155, 179069555, 141456972, 2478885421)); -    } -} diff --git a/rand/src/prng/isaac64.rs b/rand/src/prng/isaac64.rs deleted file mode 100644 index b98e3fe..0000000 --- a/rand/src/prng/isaac64.rs +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The ISAAC-64 random number generator. - -use core::slice; -use core::iter::repeat; -use core::num::Wrapping as w; -use core::fmt; - -use {Rng, SeedableRng, Rand}; - -#[allow(bad_style)] -type w64 = w<u64>; - -const RAND_SIZE_64_LEN: usize = 8; -const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN; - -/// A random number generator that uses ISAAC-64[1], the 64-bit -/// variant of the ISAAC algorithm. -/// -/// The ISAAC algorithm is generally accepted as suitable for -/// cryptographic purposes, but this implementation has not be -/// verified as such. Prefer a generator like `OsRng` that defers to -/// the operating system for cases that need high security. -/// -/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number -/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html) -#[derive(Copy)] -pub struct Isaac64Rng { -    cnt: usize, -    rsl: [w64; RAND_SIZE_64], -    mem: [w64; RAND_SIZE_64], -    a: w64, -    b: w64, -    c: w64, -} - -static EMPTY_64: Isaac64Rng = Isaac64Rng { -    cnt: 0, -    rsl: [w(0); RAND_SIZE_64], -    mem: [w(0); RAND_SIZE_64], -    a: w(0), b: w(0), c: w(0), -}; - -impl Isaac64Rng { -    /// Create a 64-bit ISAAC random number generator using the -    /// default fixed seed. -    pub fn new_unseeded() -> Isaac64Rng { -        let mut rng = EMPTY_64; -        rng.init(false); -        rng -    } - -    /// Initialises `self`. If `use_rsl` is true, then use the current value -    /// of `rsl` as a seed, otherwise construct one algorithmically (not -    /// randomly). -    fn init(&mut self, use_rsl: bool) { -        macro_rules! init { -            ($var:ident) => ( -                let mut $var = w(0x9e3779b97f4a7c13); -            ) -        } -        init!(a); init!(b); init!(c); init!(d); -        init!(e); init!(f); init!(g); init!(h); - -        macro_rules! mix { -            () => {{ -                a=a-e; f=f^(h>>9);  h=h+a; -                b=b-f; g=g^(a<<9);  a=a+b; -                c=c-g; h=h^(b>>23); b=b+c; -                d=d-h; a=a^(c<<15); c=c+d; -                e=e-a; b=b^(d>>14); d=d+e; -                f=f-b; c=c^(e<<20); e=e+f; -                g=g-c; d=d^(f>>17); f=f+g; -                h=h-d; e=e^(g<<14); g=g+h; -            }} -        } - -        for _ in 0..4 { -            mix!(); -        } - -        if use_rsl { -            macro_rules! memloop { -                ($arr:expr) => {{ -                    for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) { -                        a=a+$arr[i  ]; b=b+$arr[i+1]; -                        c=c+$arr[i+2]; d=d+$arr[i+3]; -                        e=e+$arr[i+4]; f=f+$arr[i+5]; -                        g=g+$arr[i+6]; h=h+$arr[i+7]; -                        mix!(); -                        self.mem[i  ]=a; self.mem[i+1]=b; -                        self.mem[i+2]=c; self.mem[i+3]=d; -                        self.mem[i+4]=e; self.mem[i+5]=f; -                        self.mem[i+6]=g; self.mem[i+7]=h; -                    } -                }} -            } - -            memloop!(self.rsl); -            memloop!(self.mem); -        } else { -            for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) { -                mix!(); -                self.mem[i  ]=a; self.mem[i+1]=b; -                self.mem[i+2]=c; self.mem[i+3]=d; -                self.mem[i+4]=e; self.mem[i+5]=f; -                self.mem[i+6]=g; self.mem[i+7]=h; -            } -        } - -        self.isaac64(); -    } - -    /// Refills the output buffer (`self.rsl`) -    fn isaac64(&mut self) { -        self.c = self.c + w(1); -        // abbreviations -        let mut a = self.a; -        let mut b = self.b + self.c; -        const MIDPOINT: usize =  RAND_SIZE_64 / 2; -        const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; -        macro_rules! ind { -            ($x:expr) => { -                *self.mem.get_unchecked((($x >> 3usize).0 as usize) & (RAND_SIZE_64 - 1)) -            } -        } - -        for &(mr_offset, m2_offset) in MP_VEC.iter() { -            for base in (0..MIDPOINT / 4).map(|i| i * 4) { - -                macro_rules! rngstepp { -                    ($j:expr, $shift:expr) => {{ -                        let base = base + $j; -                        let mix = a ^ (a << $shift); -                        let mix = if $j == 0 {!mix} else {mix}; - -                        unsafe { -                            let x = *self.mem.get_unchecked(base + mr_offset); -                            a = mix + *self.mem.get_unchecked(base + m2_offset); -                            let y = ind!(x) + a + b; -                            *self.mem.get_unchecked_mut(base + mr_offset) = y; - -                            b = ind!(y >> RAND_SIZE_64_LEN) + x; -                            *self.rsl.get_unchecked_mut(base + mr_offset) = b; -                        } -                    }} -                } - -                macro_rules! rngstepn { -                    ($j:expr, $shift:expr) => {{ -                        let base = base + $j; -                        let mix = a ^ (a >> $shift); -                        let mix = if $j == 0 {!mix} else {mix}; - -                        unsafe { -                            let x = *self.mem.get_unchecked(base + mr_offset); -                            a = mix + *self.mem.get_unchecked(base + m2_offset); -                            let y = ind!(x) + a + b; -                            *self.mem.get_unchecked_mut(base + mr_offset) = y; - -                            b = ind!(y >> RAND_SIZE_64_LEN) + x; -                            *self.rsl.get_unchecked_mut(base + mr_offset) = b; -                        } -                    }} -                } - -                rngstepp!(0, 21); -                rngstepn!(1, 5); -                rngstepp!(2, 12); -                rngstepn!(3, 33); -            } -        } - -        self.a = a; -        self.b = b; -        self.cnt = RAND_SIZE_64; -    } -} - -// Cannot be derived because [u32; 256] does not implement Clone -impl Clone for Isaac64Rng { -    fn clone(&self) -> Isaac64Rng { -        *self -    } -} - -impl Rng for Isaac64Rng { -    #[inline] -    fn next_u32(&mut self) -> u32 { -        self.next_u64() as u32 -    } - -    #[inline] -    fn next_u64(&mut self) -> u64 { -        if self.cnt == 0 { -            // make some more numbers -            self.isaac64(); -        } -        self.cnt -= 1; - -        // See corresponding location in IsaacRng.next_u32 for -        // explanation. -        debug_assert!(self.cnt < RAND_SIZE_64); -        self.rsl[(self.cnt % RAND_SIZE_64) as usize].0 -    } -} - -impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng { -    fn reseed(&mut self, seed: &'a [u64]) { -        // make the seed into [seed[0], seed[1], ..., seed[seed.len() -        // - 1], 0, 0, ...], to fill rng.rsl. -        let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u64)); - -        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) { -            *rsl_elem = w(seed_elem); -        } -        self.cnt = 0; -        self.a = w(0); -        self.b = w(0); -        self.c = w(0); - -        self.init(true); -    } - -    /// Create an ISAAC random number generator with a seed. This can -    /// be any length, although the maximum number of elements used is -    /// 256 and any more will be silently ignored. A generator -    /// constructed with a given seed will generate the same sequence -    /// of values as all other generators constructed with that seed. -    fn from_seed(seed: &'a [u64]) -> Isaac64Rng { -        let mut rng = EMPTY_64; -        rng.reseed(seed); -        rng -    } -} - -impl Rand for Isaac64Rng { -    fn rand<R: Rng>(other: &mut R) -> Isaac64Rng { -        let mut ret = EMPTY_64; -        unsafe { -            let ptr = ret.rsl.as_mut_ptr() as *mut u8; - -            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8); -            other.fill_bytes(slice); -        } -        ret.cnt = 0; -        ret.a = w(0); -        ret.b = w(0); -        ret.c = w(0); - -        ret.init(true); -        return ret; -    } -} - -impl fmt::Debug for Isaac64Rng { -    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -        write!(f, "Isaac64Rng {{}}") -    } -} - -#[cfg(test)] -mod test { -    use {Rng, SeedableRng}; -    use super::Isaac64Rng; - -    #[test] -    fn test_rng_64_rand_seeded() { -        let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>(); -        let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]); -        let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_64_seeded() { -        let seed: &[_] = &[1, 23, 456, 7890, 12345]; -        let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); -        let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); -        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), -                                rb.gen_ascii_chars().take(100))); -    } - -    #[test] -    fn test_rng_64_reseed() { -        let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>(); -        let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]); -        let string1: String = r.gen_ascii_chars().take(100).collect(); - -        r.reseed(&s[..]); - -        let string2: String = r.gen_ascii_chars().take(100).collect(); -        assert_eq!(string1, string2); -    } - -    #[test] -    fn test_rng_64_true_values() { -        let seed: &[_] = &[1, 23, 456, 7890, 12345]; -        let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); -        // Regression test that isaac is actually using the above vector -        let v = (0..10).map(|_| ra.next_u64()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(547121783600835980, 14377643087320773276, 17351601304698403469, -                        1238879483818134882, 11952566807690396487, 13970131091560099343, -                        4469761996653280935, 15552757044682284409, 6860251611068737823, -                        13722198873481261842)); - -        let seed: &[_] = &[12345, 67890, 54321, 9876]; -        let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); -        // skip forward to the 10000th number -        for _ in 0..10000 { rb.next_u64(); } - -        let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>(); -        assert_eq!(v, -                   vec!(18143823860592706164, 8491801882678285927, 2699425367717515619, -                        17196852593171130876, 2606123525235546165, 15790932315217671084, -                        596345674630742204, 9947027391921273664, 11788097613744130851, -                        10391409374914919106)); -    } - -    #[test] -    fn test_rng_clone() { -        let seed: &[_] = &[1, 23, 456, 7890, 12345]; -        let mut rng: Isaac64Rng = SeedableRng::from_seed(seed); -        let mut clone = rng.clone(); -        for _ in 0..16 { -            assert_eq!(rng.next_u64(), clone.next_u64()); -        } -    } -} diff --git a/rand/src/prng/mod.rs b/rand/src/prng/mod.rs index ed3e018..3c0d27b 100644 --- a/rand/src/prng/mod.rs +++ b/rand/src/prng/mod.rs @@ -1,51 +1,37 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. +// Copyright 2018 Developers of the Rand project.  //  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your  // option. This file may not be copied, modified, or distributed  // except according to those terms. -//! Pseudo random number generators are algorithms to produce *apparently -//! random* numbers deterministically, and usually fairly quickly. +//! Pseudo-random number generators. +//! +//! This module is deprecated:  //!  -//! So long as the algorithm is computationally secure, is initialised with -//! sufficient entropy (i.e. unknown by an attacker), and its internal state is -//! also protected (unknown to an attacker), the output will also be -//! *computationally secure*. Computationally Secure Pseudo Random Number -//! Generators (CSPRNGs) are thus suitable sources of random numbers for -//! cryptography. There are a couple of gotchas here, however. First, the seed -//! used for initialisation must be unknown. Usually this should be provided by -//! the operating system and should usually be secure, however this may not -//! always be the case (especially soon after startup). Second, user-space -//! memory may be vulnerable, for example when written to swap space, and after -//! forking a child process should reinitialise any user-space PRNGs. For this -//! reason it may be preferable to source random numbers directly from the OS -//! for cryptographic applications. -//!  -//! PRNGs are also widely used for non-cryptographic uses: randomised -//! algorithms, simulations, games. In these applications it is usually not -//! important for numbers to be cryptographically *unguessable*, but even -//! distribution and independence from other samples (from the point of view -//! of someone unaware of the algorithm used, at least) may still be important. -//! Good PRNGs should satisfy these properties, but do not take them for -//! granted; Wikipedia's article on  -//! [Pseudorandom number generators](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) -//! provides some background on this topic. -//!  -//! Care should be taken when seeding (initialising) PRNGs. Some PRNGs have -//! short periods for some seeds. If one PRNG is seeded from another using the -//! same algorithm, it is possible that both will yield the same sequence of -//! values (with some lag). - -mod chacha; -mod isaac; -mod isaac64; -mod xorshift; +//! -   documentation has moved to +//!     [The Book](https://rust-random.github.io/book/guide-rngs.html), +//! -   PRNGs have moved to other `rand_*` crates. -pub use self::chacha::ChaChaRng; -pub use self::isaac::IsaacRng; -pub use self::isaac64::Isaac64Rng; -pub use self::xorshift::XorShiftRng; +// Deprecations (to be removed in 0.7) +#[doc(hidden)] #[allow(deprecated)] +pub use deprecated::XorShiftRng; +#[doc(hidden)] pub mod isaac { +    // Note: we miss `IsaacCore` here but probably unimportant. +    #[allow(deprecated)] pub use deprecated::IsaacRng; +} +#[doc(hidden)] pub mod isaac64 { +    #[allow(deprecated)] pub use deprecated::Isaac64Rng; +} +#[doc(hidden)] #[allow(deprecated)] pub use deprecated::{IsaacRng, Isaac64Rng}; +#[doc(hidden)] pub mod chacha { +    // Note: we miss `ChaChaCore` here but probably unimportant. +    #[allow(deprecated)] pub use deprecated::ChaChaRng; +} +#[doc(hidden)] #[allow(deprecated)] pub use deprecated::ChaChaRng; +#[doc(hidden)] pub mod hc128 { +    // Note: we miss `Hc128Core` here but probably unimportant. +    #[allow(deprecated)] pub use deprecated::Hc128Rng; +} +#[doc(hidden)] #[allow(deprecated)] pub use deprecated::Hc128Rng; diff --git a/rand/src/prng/xorshift.rs b/rand/src/prng/xorshift.rs deleted file mode 100644 index dd367e9..0000000 --- a/rand/src/prng/xorshift.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Xorshift generators - -use core::num::Wrapping as w; -use {Rng, SeedableRng, Rand}; - -/// An Xorshift[1] random number -/// generator. -/// -/// The Xorshift algorithm is not suitable for cryptographic purposes -/// but is very fast. If you do not know for sure that it fits your -/// requirements, use a more secure one such as `IsaacRng` or `OsRng`. -/// -/// [1]: Marsaglia, George (July 2003). ["Xorshift -/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of -/// Statistical Software*. Vol. 8 (Issue 14). -#[allow(missing_copy_implementations)] -#[derive(Clone, Debug)] -pub struct XorShiftRng { -    x: w<u32>, -    y: w<u32>, -    z: w<u32>, -    w: w<u32>, -} - -impl XorShiftRng { -    /// Creates a new XorShiftRng instance which is not seeded. -    /// -    /// The initial values of this RNG are constants, so all generators created -    /// by this function will yield the same stream of random numbers. It is -    /// highly recommended that this is created through `SeedableRng` instead of -    /// this function -    pub fn new_unseeded() -> XorShiftRng { -        XorShiftRng { -            x: w(0x193a6754), -            y: w(0xa8a7d469), -            z: w(0x97830e05), -            w: w(0x113ba7bb), -        } -    } -} - -impl Rng for XorShiftRng { -    #[inline] -    fn next_u32(&mut self) -> u32 { -        let x = self.x; -        let t = x ^ (x << 11); -        self.x = self.y; -        self.y = self.z; -        self.z = self.w; -        let w_ = self.w; -        self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); -        self.w.0 -    } -} - -impl SeedableRng<[u32; 4]> for XorShiftRng { -    /// Reseed an XorShiftRng. This will panic if `seed` is entirely 0. -    fn reseed(&mut self, seed: [u32; 4]) { -        assert!(!seed.iter().all(|&x| x == 0), -                "XorShiftRng.reseed called with an all zero seed."); - -        self.x = w(seed[0]); -        self.y = w(seed[1]); -        self.z = w(seed[2]); -        self.w = w(seed[3]); -    } - -    /// Create a new XorShiftRng. This will panic if `seed` is entirely 0. -    fn from_seed(seed: [u32; 4]) -> XorShiftRng { -        assert!(!seed.iter().all(|&x| x == 0), -                "XorShiftRng::from_seed called with an all zero seed."); - -        XorShiftRng { -            x: w(seed[0]), -            y: w(seed[1]), -            z: w(seed[2]), -            w: w(seed[3]), -        } -    } -} - -impl Rand for XorShiftRng { -    fn rand<R: Rng>(rng: &mut R) -> XorShiftRng { -        let mut tuple: (u32, u32, u32, u32) = rng.gen(); -        while tuple == (0, 0, 0, 0) { -            tuple = rng.gen(); -        } -        let (x, y, z, w_) = tuple; -        XorShiftRng { x: w(x), y: w(y), z: w(z), w: w(w_) } -    } -} | 
