@@ -10,7 +10,7 @@ use core::{convert::Infallible, fmt::Debug};
1010
1111use rand_core:: {
1212 SeedableRng , TryCryptoRng , TryRng ,
13- block:: { BlockRng , CryptoGenerator , Generator } ,
13+ block:: { BlockRng , Generator } ,
1414} ;
1515
1616#[ cfg( feature = "zeroize" ) ]
@@ -77,33 +77,32 @@ impl Debug for Seed {
7777 }
7878}
7979
80- /// A wrapper around 64 bits of data that can be constructed from any of the
81- /// following:
80+ /// A wrapper for `stream_id` (64-bits).
81+ ///
82+ /// Can be constructed from any of the following:
8283/// * `u64`
8384/// * `[u32; 2]`
8485/// * `[u8; 8]`
8586///
86- /// The arrays should be in little endian order. You should not need to use
87- /// this directly, as the methods in this crate that use this type call
88- /// `.into()` for you, so you only need to supply any of the above types.
89- pub struct U32x2 ( [ u32 ; Self :: LEN ] ) ;
87+ /// The arrays should be in little endian order.
88+ pub struct StreamId ( [ u32 ; Self :: LEN ] ) ;
9089
91- impl U32x2 {
92- /// Amount of raw bytes backing a `U32x2 ` instance.
90+ impl StreamId {
91+ /// Amount of raw bytes backing a `StreamId ` instance.
9392 const BYTES : usize = size_of :: < Self > ( ) ;
9493
95- /// The length of the array contained within `U32x2 `.
94+ /// The length of the array contained within `StreamId `.
9695 const LEN : usize = 2 ;
9796}
9897
99- impl From < [ u32 ; Self :: LEN ] > for U32x2 {
98+ impl From < [ u32 ; Self :: LEN ] > for StreamId {
10099 #[ inline]
101100 fn from ( value : [ u32 ; Self :: LEN ] ) -> Self {
102101 Self ( value)
103102 }
104103}
105104
106- impl From < [ u8 ; Self :: BYTES ] > for U32x2 {
105+ impl From < [ u8 ; Self :: BYTES ] > for StreamId {
107106 #[ inline]
108107 fn from ( value : [ u8 ; Self :: BYTES ] ) -> Self {
109108 let mut result = Self ( Default :: default ( ) ) ;
@@ -118,34 +117,14 @@ impl From<[u8; Self::BYTES]> for U32x2 {
118117 }
119118}
120119
121- impl From < u64 > for U32x2 {
120+ impl From < u64 > for StreamId {
122121 #[ inline]
123122 fn from ( value : u64 ) -> Self {
124123 let result: [ u8 ; Self :: BYTES ] = value. to_le_bytes ( ) [ ..Self :: BYTES ] . try_into ( ) . unwrap ( ) ;
125124 result. into ( )
126125 }
127126}
128127
129- /// A wrapper for `stream_id`.
130- ///
131- /// Can be constructed from any of the following:
132- /// * `u64`
133- /// * `[u32; 2]`
134- /// * `[u8; 8]`
135- ///
136- /// The arrays should be in little endian order.
137- pub type StreamId = U32x2 ;
138-
139- /// A wrapper for `block_pos`.
140- ///
141- /// Can be constructed from any of the following:
142- /// * `u64`
143- /// * `[u32; 2]`
144- /// * `[u8; 8]`
145- ///
146- /// The arrays should be in little endian order.
147- pub type BlockPos = U32x2 ;
148-
149128const BUFFER_SIZE : usize = 64 ;
150129
151130// NB. this must remain consistent with some currently hard-coded numbers in this module
@@ -195,7 +174,7 @@ impl<R: Rounds, V: Variant> ChaChaCore<R, V> {
195174}
196175
197176macro_rules! impl_chacha_rng {
198- ( $ChaChaXRng: ident, $ChaChaXCore : ident , $ rounds: ident, $abst: ident) => {
177+ ( $ChaChaXRng: ident, $rounds: ident, $abst: ident) => {
199178 /// A cryptographically secure random number generator that uses the ChaCha algorithm.
200179 ///
201180 /// ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use as an RNG. It is
@@ -225,8 +204,9 @@ macro_rules! impl_chacha_rng {
225204 /// seed seed seed seed
226205 /// counter counter stream_id stream_id
227206 /// ```
228- /// This implementation uses an output buffer of sixteen `u32` words, and uses
229- /// [`BlockRng`] to implement the [`Rng`] methods.
207+ /// This implementation uses an output buffer of sixteen `u32` words, using
208+ /// [`rand_core::block::BlockRng`] over [`ChaChaCore`] to implement
209+ /// [`rand_core::Rng`].
230210 ///
231211 /// # Example for `ChaCha20Rng`
232212 ///
@@ -266,19 +246,15 @@ macro_rules! impl_chacha_rng {
266246 ///
267247 /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project](http://www.ecrypt.eu.org/stream/)
268248 pub struct $ChaChaXRng {
269- /// The ChaChaCore struct
270- pub core: BlockRng <$ChaChaXCore>,
249+ core: BlockRng <ChaChaCore <$rounds, Legacy >>,
271250 }
272251
273- /// The ChaCha core random number generator
274- pub struct $ChaChaXCore( ChaChaCore <$rounds, Legacy >) ;
275-
276- impl SeedableRng for $ChaChaXCore {
252+ impl SeedableRng for ChaChaCore <$rounds, Legacy > {
277253 type Seed = Seed ;
278254
279255 #[ inline]
280256 fn from_seed( seed: Self :: Seed ) -> Self {
281- Self ( ChaChaCore :: <$rounds, Legacy >:: new( seed. as_ref( ) , & [ 0u8 ; 8 ] ) )
257+ ChaChaCore :: <$rounds, Legacy >:: new( seed. as_ref( ) , & [ 0u8 ; 8 ] )
282258 }
283259 }
284260 impl SeedableRng for $ChaChaXRng {
@@ -287,7 +263,7 @@ macro_rules! impl_chacha_rng {
287263 #[ inline]
288264 fn from_seed( seed: Self :: Seed ) -> Self {
289265 Self {
290- core: BlockRng :: new( $ChaChaXCore :: from_seed( seed. into( ) ) ) ,
266+ core: BlockRng :: new( ChaChaCore :: <$rounds , Legacy > :: from_seed( seed. into( ) ) ) ,
291267 }
292268 }
293269 }
@@ -308,11 +284,8 @@ macro_rules! impl_chacha_rng {
308284 Ok ( ( ) )
309285 }
310286 }
311- impl CryptoGenerator for $ChaChaXCore { }
312- impl TryCryptoRng for $ChaChaXRng { }
313287
314- #[ cfg( feature = "zeroize" ) ]
315- impl ZeroizeOnDrop for $ChaChaXCore { }
288+ impl TryCryptoRng for $ChaChaXRng { }
316289
317290 #[ cfg( feature = "zeroize" ) ]
318291 impl ZeroizeOnDrop for $ChaChaXRng { }
@@ -336,8 +309,8 @@ macro_rules! impl_chacha_rng {
336309 /// byte-offset.
337310 #[ inline]
338311 pub fn get_word_pos( & self ) -> u128 {
339- let mut block_counter = ( u64 :: from( self . core. core. 0 . state[ 13 ] ) << 32 )
340- | u64 :: from( self . core. core. 0 . state[ 12 ] ) ;
312+ let mut block_counter = ( u64 :: from( self . core. core. state[ 13 ] ) << 32 )
313+ | u64 :: from( self . core. core. state[ 12 ] ) ;
341314 if self . core. word_offset( ) != 0 {
342315 block_counter = block_counter. wrapping_sub( BUF_BLOCKS as u64 ) ;
343316 }
@@ -360,8 +333,8 @@ macro_rules! impl_chacha_rng {
360333 let index = ( word_offset % BLOCK_WORDS as u128 ) as usize ;
361334 let counter = word_offset / BLOCK_WORDS as u128 ;
362335 //self.set_block_pos(counter as u64);
363- self . core. core. 0 . state[ 12 ] = counter as u32 ;
364- self . core. core. 0 . state[ 13 ] = ( counter >> 32 ) as u32 ;
336+ self . core. core. state[ 12 ] = counter as u32 ;
337+ self . core. core. state[ 13 ] = ( counter >> 32 ) as u32 ;
365338 self . core. reset_and_skip( index) ;
366339 }
367340
@@ -371,28 +344,18 @@ macro_rules! impl_chacha_rng {
371344 /// together.
372345 ///
373346 /// The word pos will be equal to `block_pos * 16 words per block`.
374- ///
375- /// This method takes any of the following:
376- /// * `u64`
377- /// * `[u32; 2]`
378- /// * `[u8; 8]`
379- ///
380- /// Note: the arrays should be in little endian order.
381347 #[ inline]
382348 #[ allow( unused) ]
383- pub fn set_block_pos< B : Into < BlockPos >> ( & mut self , block_pos: B ) {
349+ pub fn set_block_pos( & mut self , block_pos: u64 ) {
384350 self . core. reset_and_skip( 0 ) ;
385- let block_pos = block_pos. into( ) . 0 ;
386- self . core. core. 0 . state[ 12 ] = block_pos[ 0 ] ;
387- self . core. core. 0 . state[ 13 ] = block_pos[ 1 ]
351+ self . core. core. set_block_pos( block_pos) ;
388352 }
389353
390354 /// Get the block pos.
391355 #[ inline]
392356 #[ allow( unused) ]
393357 pub fn get_block_pos( & self ) -> u64 {
394- let counter =
395- self . core. core. 0 . state[ 12 ] as u64 | ( ( self . core. core. 0 . state[ 13 ] as u64 ) << 32 ) ;
358+ let counter = self . core. core. get_block_pos( ) ;
396359 if self . core. word_offset( ) != 0 {
397360 counter - BUF_BLOCKS as u64 + self . core. word_offset( ) as u64 / 16
398361 } else {
@@ -426,7 +389,7 @@ macro_rules! impl_chacha_rng {
426389 ///
427390 /// // set state[12] to 0, state[13] to 1, state[14] to 2, state[15] to 3
428391 /// rng.set_stream([2u32, 3u32]);
429- /// rng.set_block_pos([0u32, 1u32] );
392+ /// rng.set_block_pos(0x1_0000_0000_u64 );
430393 ///
431394 /// // confirm that state is set correctly
432395 /// assert_eq!(rng.get_block_pos(), 1 << 32);
@@ -440,15 +403,15 @@ macro_rules! impl_chacha_rng {
440403 #[ inline]
441404 pub fn set_stream<S : Into <StreamId >>( & mut self , stream: S ) {
442405 let stream: StreamId = stream. into( ) ;
443- self . core. core. 0 . state[ 14 ..] . copy_from_slice( & stream. 0 ) ;
406+ self . core. core. state[ 14 ..] . copy_from_slice( & stream. 0 ) ;
444407 self . set_block_pos( 0 ) ;
445408 }
446409
447410 /// Get the stream number.
448411 #[ inline]
449412 pub fn get_stream( & self ) -> u64 {
450413 let mut result = [ 0u8 ; 8 ] ;
451- for ( i, & big) in self . core. core. 0 . state[ 14 ..BLOCK_WORDS as usize ]
414+ for ( i, & big) in self . core. core. state[ 14 ..BLOCK_WORDS as usize ]
452415 . iter( )
453416 . enumerate( )
454417 {
@@ -465,7 +428,7 @@ macro_rules! impl_chacha_rng {
465428 #[ inline]
466429 pub fn get_seed( & self ) -> [ u8 ; 32 ] {
467430 let mut result = [ 0u8 ; 32 ] ;
468- for ( i, & big) in self . core. core. 0 . state[ 4 ..12 ] . iter( ) . enumerate( ) {
431+ for ( i, & big) in self . core. core. state[ 4 ..12 ] . iter( ) . enumerate( ) {
469432 let index = i * 4 ;
470433 result[ index + 0 ] = big as u8 ;
471434 result[ index + 1 ] = ( big >> 8 ) as u8 ;
@@ -486,14 +449,6 @@ macro_rules! impl_chacha_rng {
486449
487450 impl Eq for $ChaChaXRng { }
488451
489- impl From <$ChaChaXCore> for $ChaChaXRng {
490- fn from( core: $ChaChaXCore) -> Self {
491- $ChaChaXRng {
492- core: BlockRng :: new( core) ,
493- }
494- }
495- }
496-
497452 mod $abst {
498453 // The abstract state of a ChaCha stream, independent of implementation choices. The
499454 // comparison and serialization of this object is considered a semver-covered part of
@@ -529,12 +484,12 @@ macro_rules! impl_chacha_rng {
529484 }
530485 }
531486
532- impl Generator for $ChaChaXCore {
487+ impl Generator for ChaChaCore <$rounds , Legacy > {
533488 type Output = [ u32 ; BUFFER_SIZE ] ;
534489
535490 #[ inline]
536491 fn generate( & mut self , r: & mut Self :: Output ) {
537- self . 0 . generate( r) ;
492+ self . generate( r) ;
538493 }
539494
540495 #[ cfg( feature = "zeroize" ) ]
@@ -545,11 +500,11 @@ macro_rules! impl_chacha_rng {
545500 } ;
546501}
547502
548- impl_chacha_rng ! ( ChaCha8Rng , ChaCha8Core , R8 , abst8) ;
503+ impl_chacha_rng ! ( ChaCha8Rng , R8 , abst8) ;
549504
550- impl_chacha_rng ! ( ChaCha12Rng , ChaCha12Core , R12 , abst12) ;
505+ impl_chacha_rng ! ( ChaCha12Rng , R12 , abst12) ;
551506
552- impl_chacha_rng ! ( ChaCha20Rng , ChaCha20Core , R20 , abst20) ;
507+ impl_chacha_rng ! ( ChaCha20Rng , R20 , abst20) ;
553508
554509#[ cfg( test) ]
555510pub ( crate ) mod tests {
@@ -614,16 +569,12 @@ pub(crate) mod tests {
614569 rng. set_stream ( 11111111 ) ;
615570 assert_eq ! ( rng. get_stream( ) , 11111111 ) ;
616571
617- // test set_block_pos with u32
572+ // test set_block_pos with u64
618573 rng. set_block_pos ( 58392 ) ;
619574 assert_eq ! ( rng. get_block_pos( ) , 58392 ) ;
620575 // test word_pos = 16 * block_pos
621576 assert_eq ! ( rng. get_word_pos( ) , 58392 * 16 ) ;
622577
623- // test set_block_pos with [u8; 8]
624- rng. set_block_pos ( [ 77 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
625- assert_eq ! ( rng. get_block_pos( ) , 77 ) ;
626-
627578 // test set_word_pos with u64
628579 rng. set_word_pos ( 8888 ) ;
629580 assert_eq ! ( rng. get_word_pos( ) , 8888 ) ;
@@ -750,7 +701,7 @@ pub(crate) mod tests {
750701
751702 // Test block 2 by using `set_block_pos` and [u8; 8]
752703 let mut rng4 = ChaChaRng :: from_seed ( seed) ;
753- rng4. set_block_pos ( [ 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
704+ rng4. set_block_pos ( 2 ) ;
754705 results = [ 0u32 ; 16 ] ;
755706 for i in results. iter_mut ( ) {
756707 * i = rng4. next_u32 ( ) ;
@@ -821,7 +772,7 @@ pub(crate) mod tests {
821772
822773 let stream_id = hex ! ( "0000004a00000000" ) ;
823774 rng. set_stream ( stream_id) ;
824- rng. set_block_pos ( hex ! ( "0000000000000009" ) ) ;
775+ rng. set_block_pos ( u64 :: from_le_bytes ( hex ! ( "0000000000000009" ) ) ) ;
825776
826777 // The test vectors omit the first 64-bytes of the keystream
827778 let mut discard_first_64 = [ 0u8 ; 64 ] ;
@@ -920,7 +871,7 @@ pub(crate) mod tests {
920871 #[ test]
921872 fn test_chacha_word_pos_zero ( ) {
922873 let mut rng = ChaChaRng :: from_seed ( Default :: default ( ) ) ;
923- assert_eq ! ( rng. core. core. 0 . state[ 12 ] , 0 ) ;
874+ assert_eq ! ( rng. core. core. state[ 12 ] , 0 ) ;
924875 assert_eq ! ( rng. core. word_offset( ) , 0 ) ;
925876 assert_eq ! ( rng. get_word_pos( ) , 0 ) ;
926877 rng. set_word_pos ( 0 ) ;
@@ -1111,7 +1062,7 @@ pub(crate) mod tests {
11111062 let first_blocks_end_block_counter = rng. get_block_pos ( ) ;
11121063
11131064 // get first four blocks after wrapping
1114- rng. set_block_pos ( [ u32 :: MAX , u32 :: MAX ] ) ;
1065+ rng. set_block_pos ( u64 :: MAX ) ;
11151066 let mut result = [ 0u8 ; 64 * 5 ] ;
11161067 rng. fill_bytes ( & mut result) ;
11171068 assert_eq ! ( first_blocks_end_word_pos, rng. get_word_pos( ) ) ;
0 commit comments