-
-
Notifications
You must be signed in to change notification settings - Fork 480
Migrate to new rand_core utility functions
#1686
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
base: master
Are you sure you want to change the base?
Changes from all commits
e9f4e84
f5cce31
90b9fee
0baca57
9ba4cad
569262a
3f4c4c8
4767661
60baaba
2154e9f
9110387
e338cd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,8 +10,7 @@ | |
|
|
||
| use crate::guts::ChaCha; | ||
| use core::fmt; | ||
| use rand_core::block::{BlockRng, BlockRngCore, CryptoBlockRng}; | ||
| use rand_core::{CryptoRng, RngCore, SeedableRng}; | ||
| use rand_core::{CryptoRng, RngCore, SeedableRng, le}; | ||
|
|
||
| #[cfg(feature = "serde")] | ||
| use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||
|
|
@@ -21,52 +20,6 @@ const BUF_BLOCKS: u8 = 4; | |
| // number of 32-bit words per ChaCha block (fixed by algorithm definition) | ||
| const BLOCK_WORDS: u8 = 16; | ||
|
|
||
| #[repr(transparent)] | ||
| pub struct Array64<T>([T; 64]); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was needed because of the bound It's a nice but ultimately unimportant improvement of the new utility fns. |
||
| impl<T> Default for Array64<T> | ||
| where | ||
| T: Default, | ||
| { | ||
| #[rustfmt::skip] | ||
| fn default() -> Self { | ||
| Self([ | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), | ||
| ]) | ||
| } | ||
| } | ||
| impl<T> AsRef<[T]> for Array64<T> { | ||
| fn as_ref(&self) -> &[T] { | ||
| &self.0 | ||
| } | ||
| } | ||
| impl<T> AsMut<[T]> for Array64<T> { | ||
| fn as_mut(&mut self) -> &mut [T] { | ||
| &mut self.0 | ||
| } | ||
| } | ||
| impl<T> Clone for Array64<T> | ||
| where | ||
| T: Copy + Default, | ||
| { | ||
| fn clone(&self) -> Self { | ||
| let mut new = Self::default(); | ||
| new.0.copy_from_slice(&self.0); | ||
| new | ||
| } | ||
| } | ||
| impl<T> fmt::Debug for Array64<T> { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(f, "Array64 {{}}") | ||
| } | ||
| } | ||
|
|
||
| macro_rules! chacha_impl { | ||
| ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr, $abst:ident,) => { | ||
| #[doc=$doc] | ||
|
|
@@ -82,28 +35,19 @@ macro_rules! chacha_impl { | |
| } | ||
| } | ||
|
|
||
| impl BlockRngCore for $ChaChaXCore { | ||
| type Item = u32; | ||
| type Results = Array64<u32>; | ||
|
|
||
| #[inline] | ||
| fn generate(&mut self, r: &mut Self::Results) { | ||
| self.state.refill4($rounds, &mut r.0); | ||
| } | ||
| } | ||
|
|
||
| impl SeedableRng for $ChaChaXCore { | ||
| type Seed = [u8; 32]; | ||
|
|
||
| impl $ChaChaXCore { | ||
| #[inline] | ||
| fn from_seed(seed: Self::Seed) -> Self { | ||
| fn from_seed(seed: [u8; 32]) -> Self { | ||
| $ChaChaXCore { | ||
| state: ChaCha::new(&seed, &[0u8; 8]), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl CryptoBlockRng for $ChaChaXCore {} | ||
| #[inline] | ||
| fn next_block(&mut self, r: &mut [u32; 64]) { | ||
| self.state.refill4($rounds, r); | ||
| } | ||
| } | ||
|
|
||
| /// A cryptographically secure random number generator that uses the ChaCha algorithm. | ||
| /// | ||
|
|
@@ -136,7 +80,7 @@ macro_rules! chacha_impl { | |
| /// ``` | ||
| /// | ||
| /// This implementation uses an output buffer of sixteen `u32` words, and uses | ||
| /// [`BlockRng`] to implement the [`RngCore`] methods. | ||
| /// them to implement the [`RngCore`] methods. | ||
| /// | ||
| /// [^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( | ||
| /// https://cr.yp.to/chacha.html) | ||
|
|
@@ -145,35 +89,55 @@ macro_rules! chacha_impl { | |
| /// http://www.ecrypt.eu.org/stream/) | ||
| #[derive(Clone, Debug)] | ||
| pub struct $ChaChaXRng { | ||
| rng: BlockRng<$ChaChaXCore>, | ||
| core: $ChaChaXCore, | ||
| buffer: [u32; 64], | ||
| } | ||
|
|
||
| impl $ChaChaXRng { | ||
| fn buffer_index(&self) -> u32 { | ||
| self.buffer[0] | ||
| } | ||
|
|
||
| fn generate_and_set(&mut self, index: usize) { | ||
| assert!(index < self.buffer.len()); | ||
| self.buffer[0] = if index != 0 { | ||
| self.core.next_block(&mut self.buffer); | ||
| index as u32 | ||
| } else { | ||
| self.buffer.len() as u32 | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+96
to
110
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These feel like low-level details. They very much depend on using We could fix this with a |
||
|
|
||
| impl SeedableRng for $ChaChaXRng { | ||
| type Seed = [u8; 32]; | ||
|
|
||
| #[inline] | ||
| fn from_seed(seed: Self::Seed) -> Self { | ||
| let core = $ChaChaXCore::from_seed(seed); | ||
| Self { | ||
| rng: BlockRng::new(core), | ||
| core: $ChaChaXCore::from_seed(seed), | ||
| buffer: le::new_buffer(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl RngCore for $ChaChaXRng { | ||
| #[inline] | ||
| fn next_u32(&mut self) -> u32 { | ||
| self.rng.next_u32() | ||
| let Self { core, buffer } = self; | ||
| le::next_word_via_gen_block(buffer, |block| core.next_block(block)) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn next_u64(&mut self) -> u64 { | ||
| self.rng.next_u64() | ||
| let Self { core, buffer } = self; | ||
| le::next_u64_via_gen_block(buffer, |block| core.next_block(block)) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn fill_bytes(&mut self, bytes: &mut [u8]) { | ||
| self.rng.fill_bytes(bytes) | ||
| fn fill_bytes(&mut self, dst: &mut [u8]) { | ||
| let Self { core, buffer } = self; | ||
| le::fill_bytes_via_gen_block(dst, buffer, |block| core.next_block(block)); | ||
| } | ||
|
Comment on lines
116
to
141
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This stuff all requires marginally lower-level implementations; not very significant. |
||
| } | ||
|
|
||
|
|
@@ -190,11 +154,11 @@ macro_rules! chacha_impl { | |
| #[inline] | ||
| pub fn get_word_pos(&self) -> u128 { | ||
| let buf_start_block = { | ||
| let buf_end_block = self.rng.core.state.get_block_pos(); | ||
| let buf_end_block = self.core.state.get_block_pos(); | ||
| u64::wrapping_sub(buf_end_block, BUF_BLOCKS.into()) | ||
| }; | ||
| let (buf_offset_blocks, block_offset_words) = { | ||
| let buf_offset_words = self.rng.index() as u64; | ||
| let buf_offset_words = self.buffer_index() as u64; | ||
| let blocks_part = buf_offset_words / u64::from(BLOCK_WORDS); | ||
| let words_part = buf_offset_words % u64::from(BLOCK_WORDS); | ||
| (blocks_part, words_part) | ||
|
|
@@ -212,9 +176,8 @@ macro_rules! chacha_impl { | |
| #[inline] | ||
| pub fn set_word_pos(&mut self, word_offset: u128) { | ||
| let block = (word_offset / u128::from(BLOCK_WORDS)) as u64; | ||
| self.rng.core.state.set_block_pos(block); | ||
| self.rng | ||
| .generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize); | ||
| self.core.state.set_block_pos(block); | ||
| self.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize); | ||
| } | ||
|
|
||
| /// Set the stream number. | ||
|
|
@@ -230,8 +193,8 @@ macro_rules! chacha_impl { | |
| /// indirectly via `set_word_pos`), but this is not directly supported. | ||
| #[inline] | ||
| pub fn set_stream(&mut self, stream: u64) { | ||
| self.rng.core.state.set_nonce(stream); | ||
| if self.rng.index() != 64 { | ||
| self.core.state.set_nonce(stream); | ||
| if self.buffer_index() != 64 { | ||
| let wp = self.get_word_pos(); | ||
| self.set_word_pos(wp); | ||
| } | ||
|
|
@@ -240,13 +203,13 @@ macro_rules! chacha_impl { | |
| /// Get the stream number. | ||
| #[inline] | ||
| pub fn get_stream(&self) -> u64 { | ||
| self.rng.core.state.get_nonce() | ||
| self.core.state.get_nonce() | ||
| } | ||
|
|
||
| /// Get the seed. | ||
| #[inline] | ||
| pub fn get_seed(&self) -> [u8; 32] { | ||
| self.rng.core.state.get_seed() | ||
| self.core.state.get_seed() | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -255,7 +218,8 @@ macro_rules! chacha_impl { | |
| impl From<$ChaChaXCore> for $ChaChaXRng { | ||
| fn from(core: $ChaChaXCore) -> Self { | ||
| $ChaChaXRng { | ||
| rng: BlockRng::new(core), | ||
| core, | ||
| buffer: le::new_buffer(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.