Skip to content

ChaCha: support reading counter and setting nonce #374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 3 additions & 50 deletions benches/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ macro_rules! gen_bytes {
}

gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy());
gen_bytes!(gen_bytes_chacha20, ChaChaRng::from_entropy());
gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy());
gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy());
gen_bytes!(gen_bytes_isaac64, Isaac64Rng::from_entropy());
Expand All @@ -59,6 +60,7 @@ macro_rules! gen_uint {
}

gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy());
gen_uint!(gen_u32_chacha20, u32, ChaChaRng::from_entropy());
gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy());
gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy());
gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::from_entropy());
Expand All @@ -67,6 +69,7 @@ gen_uint!(gen_u32_small, u32, SmallRng::from_entropy());
gen_uint!(gen_u32_os, u32, OsRng::new().unwrap());

gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy());
gen_uint!(gen_u64_chacha20, u64, ChaChaRng::from_entropy());
gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy());
gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy());
gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::from_entropy());
Expand Down Expand Up @@ -111,56 +114,6 @@ fn init_jitter(b: &mut Bencher) {
});
}

macro_rules! chacha_rounds {
($fn1:ident, $fn2:ident, $fn3:ident, $rounds:expr) => {
#[bench]
fn $fn1(b: &mut Bencher) {
let mut rng = ChaChaRng::from_entropy();
rng.set_rounds($rounds);
let mut buf = [0u8; BYTES_LEN];
b.iter(|| {
for _ in 0..RAND_BENCH_N {
rng.fill_bytes(&mut buf);
black_box(buf);
}
});
b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
}

#[bench]
fn $fn2(b: &mut Bencher) {
let mut rng = ChaChaRng::from_entropy();
rng.set_rounds($rounds);
b.iter(|| {
let mut accum: u32 = 0;
for _ in 0..RAND_BENCH_N {
accum = accum.wrapping_add(rng.gen::<u32>());
}
black_box(accum);
});
b.bytes = size_of::<u32>() as u64 * RAND_BENCH_N;
}

#[bench]
fn $fn3(b: &mut Bencher) {
let mut rng = ChaChaRng::from_entropy();
rng.set_rounds($rounds);
b.iter(|| {
let mut accum: u64 = 0;
for _ in 0..RAND_BENCH_N {
accum = accum.wrapping_add(rng.gen::<u64>());
}
black_box(accum);
});
b.bytes = size_of::<u64>() as u64 * RAND_BENCH_N;
}
}
}

chacha_rounds!(gen_bytes_chacha8, gen_u32_chacha8, gen_u64_chacha8, 8);
chacha_rounds!(gen_bytes_chacha12, gen_u32_chacha12, gen_u64_chacha12, 12);
chacha_rounds!(gen_bytes_chacha20, gen_u32_chacha20, gen_u64_chacha20, 20);


const RESEEDING_THRESHOLD: u64 = 1024*1024*1024; // something high enough to get
// deterministic measurements
Expand Down
37 changes: 25 additions & 12 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,28 @@ impl<R: BlockRngCore> BlockRng<R> {
&mut self.core
}

// Reset the number of available results.
// This will force a new set of results to be generated on next use.
/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
/// the buffer is "empty" and `generate()` must be called to produce new
/// results.
pub fn index(&self) -> usize {
self.index
}

/// Reset the number of available results.
/// This will force a new set of results to be generated on next use.
pub fn reset(&mut self) {
self.index = self.results.as_ref().len();
}

/// Generate a new set of results immediately, setting the index to the
/// given value.
pub fn generate_and_set(&mut self, index: usize) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, you agree. Given that I wanted to avoid/minimise breakage with the published API, this seemed like the best option.

assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
self.index = index;
}
}

impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
Expand All @@ -241,8 +258,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
#[inline(always)]
fn next_u32(&mut self) -> u32 {
if self.index >= self.results.as_ref().len() {
self.core.generate(&mut self.results);
self.index = 0;
self.generate_and_set(0);
}

let value = self.results.as_ref()[self.index];
Expand Down Expand Up @@ -271,13 +287,11 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
// Read an u64 from the current index
read_u64(self.results.as_ref(), index)
} else if index >= len {
self.core.generate(&mut self.results);
self.index = 2;
self.generate_and_set(2);
read_u64(self.results.as_ref(), 0)
} else {
let x = u64::from(self.results.as_ref()[len-1]);
self.core.generate(&mut self.results);
self.index = 1;
self.generate_and_set(1);
let y = u64::from(self.results.as_ref()[0]);
(y << 32) | x
}
Expand Down Expand Up @@ -311,8 +325,8 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
};
self.core.generate(dest_u32);
filled += self.results.as_ref().len() * 4;
self.index = self.results.as_ref().len();
}
self.index = self.results.as_ref().len();

if len_remainder > 0 {
self.core.generate(&mut self.results);
Expand All @@ -329,8 +343,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
let mut read_len = 0;
while read_len < dest.len() {
if self.index >= self.results.as_ref().len() {
self.core.generate(&mut self.results);
self.index = 0;
self.generate_and_set(0);
}
let (consumed_u32, filled_u8) =
fill_via_u32_chunks(&self.results.as_ref()[self.index..],
Expand Down Expand Up @@ -489,8 +502,8 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
};
self.core.generate(dest_u64);
filled += self.results.as_ref().len() * 8;
self.index = self.results.as_ref().len();
}
self.index = self.results.as_ref().len();

if len_remainder > 0 {
self.core.generate(&mut self.results);
Expand Down
Loading