1111
1212pub use digest;
1313use keccak:: { Keccak , State1600 } ;
14+ use sponge_cursor:: SpongeCursor ;
1415
1516use core:: fmt;
1617use digest:: {
17- CollisionResistance , ExtendableOutput , ExtendableOutputReset , HashMarker , Update , XofReader ,
18- block_api:: { AlgorithmName , BlockSizeUser , Reset } ,
19- block_buffer:: { BlockSizes , EagerBuffer , ReadBuffer } ,
18+ CollisionResistance , ExtendableOutput , ExtendableOutputReset , HashMarker , Reset , Update ,
19+ XofReader ,
20+ array:: ArraySize ,
21+ common:: { AlgorithmName , BlockSizeUser } ,
2022 consts:: { U16 , U32 , U136 , U168 } ,
2123} ;
2224
@@ -33,13 +35,13 @@ pub const DEFAULT_DS: u8 = 0x1F;
3335///
3436/// Rate MUST be either [`U168`] or [`U136`] for TurboSHAKE128 and TurboSHAKE256 respectively.
3537#[ derive( Clone ) ]
36- pub struct TurboShake < Rate : BlockSizes , const DS : u8 > {
38+ pub struct TurboShake < Rate : ArraySize , const DS : u8 > {
3739 state : State1600 ,
40+ cursor : SpongeCursor < Rate > ,
3841 keccak : Keccak ,
39- buffer : EagerBuffer < Rate > ,
4042}
4143
42- impl < Rate : BlockSizes , const DS : u8 > Default for TurboShake < Rate , DS > {
44+ impl < Rate : ArraySize , const DS : u8 > Default for TurboShake < Rate , DS > {
4345 #[ inline]
4446 fn default ( ) -> Self {
4547 const {
@@ -48,96 +50,76 @@ impl<Rate: BlockSizes, const DS: u8> Default for TurboShake<Rate, DS> {
4850 }
4951 Self {
5052 state : Default :: default ( ) ,
53+ cursor : Default :: default ( ) ,
5154 keccak : Keccak :: new ( ) ,
52- buffer : Default :: default ( ) ,
5355 }
5456 }
5557}
5658
57- impl < Rate : BlockSizes , const DS : u8 > HashMarker for TurboShake < Rate , DS > { }
59+ impl < Rate : ArraySize , const DS : u8 > HashMarker for TurboShake < Rate , DS > { }
5860
59- impl < Rate : BlockSizes , const DS : u8 > BlockSizeUser for TurboShake < Rate , DS > {
61+ impl < Rate : ArraySize , const DS : u8 > BlockSizeUser for TurboShake < Rate , DS > {
6062 type BlockSize = Rate ;
6163}
6264
63- impl < Rate : BlockSizes , const DS : u8 > Update for TurboShake < Rate , DS > {
65+ impl < Rate : ArraySize , const DS : u8 > Update for TurboShake < Rate , DS > {
6466 #[ inline]
6567 fn update ( & mut self , data : & [ u8 ] ) {
66- let Self {
67- state,
68- keccak,
69- buffer,
70- } = self ;
71-
72- keccak. with_p1600 :: < ROUNDS > ( |p1600| {
73- buffer. digest_blocks ( data, |blocks| {
74- for block in blocks {
75- xor_block ( state, block) ;
76- p1600 ( state) ;
77- }
78- } ) ;
68+ self . keccak . with_p1600 :: < ROUNDS > ( |p1600| {
69+ self . cursor . absorb_u64_le ( & mut self . state , p1600, data) ;
7970 } ) ;
8071 }
8172}
8273
83- impl < Rate : BlockSizes , const DS : u8 > TurboShake < Rate , DS > {
84- fn finalize_dirty ( & mut self ) {
85- let Self {
86- state,
87- keccak,
88- buffer,
89- } = self ;
90-
91- let pos = buffer. get_pos ( ) ;
92- let mut block = buffer. pad_with_zeros ( ) ;
93- block[ pos] = DS ;
94- let n = block. len ( ) ;
95- block[ n - 1 ] |= 0x80 ;
74+ impl < Rate : ArraySize , const DS : u8 > TurboShake < Rate , DS > {
75+ fn pad ( & mut self ) {
76+ let pos = self . cursor . pos ( ) ;
77+ let word_offset = pos / 8 ;
78+ let byte_offset = pos % 8 ;
9679
97- keccak. with_p1600 :: < ROUNDS > ( |p1600| {
98- xor_block ( state, & block) ;
99- p1600 ( state) ;
100- } ) ;
80+ let pad = u64:: from ( DS ) << ( 8 * byte_offset) ;
81+ self . state [ word_offset] ^= pad;
82+ self . state [ Rate :: USIZE / 8 - 1 ] ^= 1 << 63 ;
10183 }
10284}
10385
104- impl < Rate : BlockSizes , const DS : u8 > ExtendableOutput for TurboShake < Rate , DS > {
86+ impl < Rate : ArraySize , const DS : u8 > ExtendableOutput for TurboShake < Rate , DS > {
10587 type Reader = TurboShakeReader < Rate > ;
10688
10789 #[ inline]
10890 fn finalize_xof ( mut self ) -> Self :: Reader {
109- self . finalize_dirty ( ) ;
91+ self . pad ( ) ;
11092 Self :: Reader {
11193 state : self . state ,
94+ cursor : Default :: default ( ) ,
11295 keccak : self . keccak ,
113- buffer : Default :: default ( ) ,
11496 }
11597 }
11698}
11799
118- impl < Rate : BlockSizes , const DS : u8 > ExtendableOutputReset for TurboShake < Rate , DS > {
100+ impl < Rate : ArraySize , const DS : u8 > ExtendableOutputReset for TurboShake < Rate , DS > {
119101 #[ inline]
120102 fn finalize_xof_reset ( & mut self ) -> Self :: Reader {
121- self . finalize_dirty ( ) ;
103+ self . pad ( ) ;
122104 let reader = Self :: Reader {
123105 state : self . state ,
106+ cursor : Default :: default ( ) ,
124107 keccak : self . keccak ,
125- buffer : Default :: default ( ) ,
126108 } ;
127109 self . reset ( ) ;
128110 reader
129111 }
130112}
131113
132- impl < Rate : BlockSizes , const DS : u8 > Reset for TurboShake < Rate , DS > {
114+ impl < Rate : ArraySize , const DS : u8 > Reset for TurboShake < Rate , DS > {
133115 #[ inline]
134116 fn reset ( & mut self ) {
135117 self . state = Default :: default ( ) ;
136- self . buffer . reset ( ) ;
118+ self . cursor = Default :: default ( ) ;
137119 }
138120}
139121
140- impl < Rate : BlockSizes , const DS : u8 > AlgorithmName for TurboShake < Rate , DS > {
122+ impl < Rate : ArraySize , const DS : u8 > AlgorithmName for TurboShake < Rate , DS > {
141123 fn write_alg_name ( f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
142124 let alg_name = match Rate :: USIZE {
143125 168 => "TurboSHAKE128" ,
@@ -148,7 +130,7 @@ impl<Rate: BlockSizes, const DS: u8> AlgorithmName for TurboShake<Rate, DS> {
148130 }
149131}
150132
151- impl < Rate : BlockSizes , const DS : u8 > fmt:: Debug for TurboShake < Rate , DS > {
133+ impl < Rate : ArraySize , const DS : u8 > fmt:: Debug for TurboShake < Rate , DS > {
152134 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
153135 let debug_str = match Rate :: USIZE {
154136 168 => "TurboShake128 { ... }" ,
@@ -159,7 +141,7 @@ impl<Rate: BlockSizes, const DS: u8> fmt::Debug for TurboShake<Rate, DS> {
159141 }
160142}
161143
162- impl < Rate : BlockSizes , const DS : u8 > Drop for TurboShake < Rate , DS > {
144+ impl < Rate : ArraySize , const DS : u8 > Drop for TurboShake < Rate , DS > {
163145 fn drop ( & mut self ) {
164146 #[ cfg( feature = "zeroize" ) ]
165147 {
@@ -171,40 +153,26 @@ impl<Rate: BlockSizes, const DS: u8> Drop for TurboShake<Rate, DS> {
171153}
172154
173155#[ cfg( feature = "zeroize" ) ]
174- impl < Rate : BlockSizes , const DS : u8 > digest:: zeroize:: ZeroizeOnDrop for TurboShake < Rate , DS > { }
156+ impl < Rate : ArraySize , const DS : u8 > digest:: zeroize:: ZeroizeOnDrop for TurboShake < Rate , DS > { }
175157
176158/// Generic TurboSHAKE XOF reader
177159#[ derive( Clone ) ]
178- pub struct TurboShakeReader < Rate : BlockSizes > {
160+ pub struct TurboShakeReader < Rate : ArraySize > {
179161 state : State1600 ,
162+ cursor : SpongeCursor < Rate > ,
180163 keccak : Keccak ,
181- buffer : ReadBuffer < Rate > ,
182164}
183165
184- impl < Rate : BlockSizes > XofReader for TurboShakeReader < Rate > {
166+ impl < Rate : ArraySize > XofReader for TurboShakeReader < Rate > {
185167 #[ inline]
186168 fn read ( & mut self , buf : & mut [ u8 ] ) {
187- let Self {
188- state,
189- keccak,
190- buffer,
191- } = self ;
192-
193- buffer. read ( buf, |block| {
194- let mut chunks = block. chunks_exact_mut ( 8 ) ;
195- for ( src, dst) in state. iter ( ) . zip ( & mut chunks) {
196- dst. copy_from_slice ( & src. to_le_bytes ( ) ) ;
197- }
198- assert ! (
199- chunks. into_remainder( ) . is_empty( ) ,
200- "rate is either 136 or 168" ,
201- ) ;
202- keccak. with_p1600 :: < ROUNDS > ( |p1600| p1600 ( state) ) ;
169+ self . keccak . with_p1600 :: < ROUNDS > ( |p1600| {
170+ self . cursor . squeeze_u64_le ( & mut self . state , p1600, buf) ;
203171 } ) ;
204172 }
205173}
206174
207- impl < Rate : BlockSizes > fmt:: Debug for TurboShakeReader < Rate > {
175+ impl < Rate : ArraySize > fmt:: Debug for TurboShakeReader < Rate > {
208176 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
209177 let debug_str = match Rate :: USIZE {
210178 168 => "TurboShakeReader128 { ... }" ,
@@ -215,19 +183,19 @@ impl<Rate: BlockSizes> fmt::Debug for TurboShakeReader<Rate> {
215183 }
216184}
217185
218- impl < Rate : BlockSizes > Drop for TurboShakeReader < Rate > {
186+ impl < Rate : ArraySize > Drop for TurboShakeReader < Rate > {
219187 fn drop ( & mut self ) {
220188 #[ cfg( feature = "zeroize" ) ]
221189 {
222190 use digest:: zeroize:: Zeroize ;
223191 self . state . zeroize ( ) ;
224- // self.buffer is zeroized by its `Drop`
192+ self . cursor . zeroize ( ) ;
225193 }
226194 }
227195}
228196
229197#[ cfg( feature = "zeroize" ) ]
230- impl < Rate : BlockSizes > digest:: zeroize:: ZeroizeOnDrop for TurboShakeReader < Rate > { }
198+ impl < Rate : ArraySize > digest:: zeroize:: ZeroizeOnDrop for TurboShakeReader < Rate > { }
231199
232200/// TurboSHAKE128 hasher with domain separator.
233201pub type TurboShake128 < const DS : u8 = DEFAULT_DS > = TurboShake < U168 , DS > ;
@@ -248,15 +216,3 @@ impl<const DS: u8> CollisionResistance for TurboShake256<DS> {
248216 // https://www.ietf.org/archive/id/draft-irtf-cfrg-kangarootwelve-17.html#section-7-8
249217 type CollisionResistance = U32 ;
250218}
251-
252- fn xor_block ( state : & mut State1600 , block : & [ u8 ] ) {
253- assert ! ( size_of_val( block) < size_of_val( state) ) ;
254-
255- let mut chunks = block. chunks_exact ( 8 ) ;
256- for ( s, chunk) in state. iter_mut ( ) . zip ( & mut chunks) {
257- * s ^= u64:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
258- }
259-
260- let rem = chunks. remainder ( ) ;
261- assert ! ( rem. is_empty( ) , "block size is equal to 136 or 168" ) ;
262- }
0 commit comments