Skip to content

Commit

Permalink
Add serde framework
Browse files Browse the repository at this point in the history
  • Loading branch information
UserAB1236872 committed Jan 22, 2018
1 parent 06fb7d9 commit 3b9b943
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 45 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ matrix:
script:
- cargo test
- cargo test --tests --no-default-features
- cargo test --features serde-1
- cargo test --manifest-path rand-derive/Cargo.toml

env:
Expand Down
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,26 @@ alloc = [] # enables Vec and Box support without std

i128_support = [] # enables i128 and u128 support

serde-1 = ["serde", "serde_derive"]


[target.'cfg(unix)'.dependencies]
libc = { version = "0.2", optional = true }

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "profileapi", "winnt"], optional = true }

[dependencies]
serde = {version="1",optional=true}
serde_derive = {version="1", optional=true}

[dev-dependencies]
log = "0.3.0"
# This is for testing serde, unfortunately
# we can't specify feature-gated dev deps yet,
# see: https://github.com/rust-lang/cargo/issues/1596
bincode = "0.9"

[workspace]
members = ["rand-derive"]

Expand Down
1 change: 1 addition & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ build: false
test_script:
- cargo test --benches
- cargo test
- cargo test --features serde-1
- cargo test --features nightly
- cargo test --tests --no-default-features --features=alloc
- cargo test --manifest-path rand-derive/Cargo.toml
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@

#[cfg(feature="std")] extern crate std as core;
#[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc;
#[cfg(test)] #[macro_use] extern crate log;
#[cfg(test)] #[cfg(feature="serde-1")] extern crate bincode;
#[cfg(feature="serde-1")] extern crate serde;
#[cfg(feature="serde-1")] #[macro_use] extern crate serde_derive;

use core::marker;
use core::mem;
Expand Down
168 changes: 123 additions & 45 deletions src/prng/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//! The ChaCha random number generator.

use core::fmt;
use {Rng, SeedableRng, Rand};
use {Rand, Rng, SeedableRng};
use impls;

const KEY_WORDS : usize = 8; // 8 words for the 256-bit key
const STATE_WORDS : usize = 16;
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].
Expand All @@ -29,9 +29,9 @@ const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of
/// Salsa20*](https://cr.yp.to/chacha.html)
#[derive(Clone)]
pub struct ChaChaRng {
buffer: [u32; STATE_WORDS], // Internal buffer of output
state: [u32; STATE_WORDS], // Initial state
index: usize, // Index into state
buffer: [u32; STATE_WORDS], // Internal buffer of output
state: [u32; STATE_WORDS], // Initial state
index: usize, // Index into state
}

// Custom Debug implementation that does not expose the internal state
Expand Down Expand Up @@ -79,7 +79,6 @@ fn core(new: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
}

impl ChaChaRng {

/// Create an ChaCha random number generator using the default
/// fixed key of 8 zero words.
///
Expand All @@ -101,9 +100,9 @@ impl ChaChaRng {
/// - 2419978656
pub fn new_unseeded() -> ChaChaRng {
let mut rng = ChaChaRng {
buffer: [0; STATE_WORDS],
state: [0; STATE_WORDS],
index: STATE_WORDS
buffer: [0; STATE_WORDS],
state: [0; STATE_WORDS],
index: STATE_WORDS,
};
rng.init(&[0; KEY_WORDS]);
rng
Expand All @@ -129,9 +128,9 @@ impl ChaChaRng {
/// println!("{:?}", ra.next_u32());
/// ```
pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
self.state[12] = (counter_low >> 0) as u32;
self.state[12] = (counter_low >> 0) as u32;
self.state[13] = (counter_low >> 32) as u32;
self.state[14] = (counter_high >> 0) as u32;
self.state[14] = (counter_high >> 0) as u32;
self.state[15] = (counter_high >> 32) as u32;
self.index = STATE_WORDS; // force recomputation
}
Expand Down Expand Up @@ -161,7 +160,7 @@ impl ChaChaRng {
self.state[3] = 0x6B206574;

for i in 0..KEY_WORDS {
self.state[4+i] = key[i];
self.state[4 + i] = key[i];
}

self.state[12] = 0;
Expand All @@ -178,11 +177,17 @@ impl ChaChaRng {
self.index = 0;
// update 128-bit counter
self.state[12] = self.state[12].wrapping_add(1);
if self.state[12] != 0 { return };
if self.state[12] != 0 {
return;
};
self.state[13] = self.state[13].wrapping_add(1);
if self.state[13] != 0 { return };
if self.state[13] != 0 {
return;
};
self.state[14] = self.state[14].wrapping_add(1);
if self.state[14] != 0 { return };
if self.state[14] != 0 {
return;
};
self.state[15] = self.state[15].wrapping_add(1);
}
}
Expand Down Expand Up @@ -216,8 +221,7 @@ impl Rng for ChaChaRng {
}

let (consumed_u32, filled_u8) =
impls::fill_via_u32_chunks(&self.buffer[self.index..],
&mut dest[read_len..]);
impls::fill_via_u32_chunks(&self.buffer[self.index..], &mut dest[read_len..]);

self.index += consumed_u32;
read_len += filled_u8;
Expand All @@ -226,7 +230,6 @@ impl Rng for ChaChaRng {
}

impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {

fn reseed(&mut self, seed: &'a [u32]) {
*self = Self::from_seed(seed);
}
Expand All @@ -237,14 +240,14 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
/// words are used, the remaining are set to zero.
fn from_seed(seed: &'a [u32]) -> ChaChaRng {
let mut rng = ChaChaRng {
buffer: [0; STATE_WORDS],
state: [0; STATE_WORDS],
index: STATE_WORDS
buffer: [0; STATE_WORDS],
state: [0; STATE_WORDS],
index: STATE_WORDS,
};
rng.init(&[0u32; KEY_WORDS]);
// set key in place
{
let key = &mut rng.state[4 .. 4+KEY_WORDS];
let key = &mut rng.state[4..4 + KEY_WORDS];
for (k, s) in key.iter_mut().zip(seed.iter()) {
*k = *s;
}
Expand All @@ -255,15 +258,14 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {

impl Rand for ChaChaRng {
fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
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};
Expand All @@ -289,22 +291,54 @@ mod test {
let mut rng1: ChaChaRng = SeedableRng::from_seed(seed);

let mut results = [0u32; 16];
for i in results.iter_mut() { *i = rng1.next_u32(); }
let expected = [0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653,
0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b,
0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8,
0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2];
for i in results.iter_mut() {
*i = rng1.next_u32();
}
let expected = [
0xade0b876,
0x903df1a0,
0xe56a5d40,
0x28bd8653,
0xb819d2bd,
0x1aed8da0,
0xccef36a8,
0xc70d778b,
0x7c5941da,
0x8d485751,
0x3fe02477,
0x374ad8b8,
0xf4b8436a,
0x1ca11815,
0x69b687c3,
0x8665eeb2,
];
assert_eq!(results, expected);

for i in results.iter_mut() { *i = rng1.next_u32(); }
let expected = [0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73,
0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32,
0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874,
0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b];
for i in results.iter_mut() {
*i = rng1.next_u32();
}
let expected = [
0xbee7079f,
0x7a385155,
0x7c97ba98,
0x0d082d73,
0xa0290fcb,
0x6965e348,
0x3e53c612,
0xed7aee32,
0x7621b729,
0x434ee69c,
0xb03371d5,
0xd539d874,
0x281fed31,
0x45fb0a51,
0x1f0ae1ac,
0x6f4d794b,
];
assert_eq!(results, expected);


let seed: &[_] = &[0,1,2,3,4,5,6,7];
let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
let mut rng2: ChaChaRng = SeedableRng::from_seed(seed);

// Store the 17*i-th 32-bit word,
Expand All @@ -315,10 +349,24 @@ mod test {
rng2.next_u32();
}
}
let expected = [0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036,
0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384,
0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4];
let expected = [
0xf225c81a,
0x6ab1be57,
0x04d42951,
0x70858036,
0x49884684,
0x64efec72,
0x4be2d186,
0x3615b384,
0x11cfa18e,
0xd3c50049,
0x75c775f6,
0x434c6530,
0x2c5bad8f,
0x898881dc,
0x5f1c86d9,
0xc1f8e7f4,
];
assert_eq!(results, expected);
}

Expand All @@ -329,16 +377,46 @@ mod test {
let mut results = [0u8; 32];
rng.fill_bytes(&mut results);
// Same as first values in test_isaac_true_values as bytes in LE order
let expected = [118, 184, 224, 173, 160, 241, 61, 144,
64, 93, 106, 229, 83, 134, 189, 40,
189, 210, 25, 184, 160, 141, 237, 26,
168, 54, 239, 204, 139, 119, 13, 199];
let expected = [
118,
184,
224,
173,
160,
241,
61,
144,
64,
93,
106,
229,
83,
134,
189,
40,
189,
210,
25,
184,
160,
141,
237,
26,
168,
54,
239,
204,
139,
119,
13,
199,
];
assert_eq!(results, expected);
}

#[test]
fn test_chacha_clone() {
let seed: &[_] = &[0,1,2,3,4,5,6,7];
let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
let mut clone = rng.clone();
for _ in 0..16 {
Expand Down

0 comments on commit 3b9b943

Please sign in to comment.