44//! It is designed to match test vectors from the original Sage implementation.
55
66use crate :: duplex_sponge:: DuplexSpongeInterface ;
7- use std:: convert:: TryInto ;
8- use tiny_keccak:: keccakf;
7+ use zerocopy:: IntoBytes ;
98
10- const R : usize = 136 ;
11- const N : usize = 136 + 64 ;
9+ const RATE : usize = 136 ;
10+ const LENGTH : usize = 136 + 64 ;
1211
1312/// Low-level Keccak-f[1600] state representation.
14- #[ derive( Clone ) ]
15- pub struct KeccakPermutationState {
16- pub state : [ u8 ; 200 ] ,
17- pub rate : usize ,
18- pub capacity : usize ,
19- }
20-
21- impl Default for KeccakPermutationState {
22- fn default ( ) -> Self {
23- Self :: new ( [ 0u8 ; 32 ] )
24- }
25- }
13+ #[ derive( Clone , Default ) ]
14+ pub struct KeccakPermutationState ( [ u64 ; LENGTH / 8 ] ) ;
2615
2716impl KeccakPermutationState {
2817 pub fn new ( iv : [ u8 ; 32 ] ) -> Self {
29- let rate = 136 ;
30- let mut state = [ 0u8 ; N ] ;
31- state[ rate..rate + 32 ] . copy_from_slice ( & iv) ;
32-
33- KeccakPermutationState {
34- state,
35- rate,
36- capacity : 64 ,
37- }
18+ let mut state = Self :: default ( ) ;
19+ state. as_mut ( ) [ RATE ..RATE + 32 ] . copy_from_slice ( & iv) ;
20+ state
3821 }
3922
40- fn bytes_to_flat_state ( & self ) -> [ u64 ; 25 ] {
41- let mut flat = [ 0u64 ; 25 ] ;
42- for ( i, item) in flat. iter_mut ( ) . enumerate ( ) {
43- let start = i * 8 ;
44- * item = u64:: from_le_bytes ( self . state [ start..start + 8 ] . try_into ( ) . unwrap ( ) ) ;
45- }
46- flat
23+ pub fn permute ( & mut self ) {
24+ keccak:: f1600 ( & mut self . 0 ) ;
4725 }
26+ }
4827
49- fn flat_state_to_bytes ( & mut self , flat : [ u64 ; 25 ] ) {
50- for ( i, item) in flat. iter ( ) . enumerate ( ) {
51- let bytes = item. to_le_bytes ( ) ;
52- let start = i * 8 ;
53- self . state [ start..start + 8 ] . copy_from_slice ( & bytes) ;
54- }
28+ impl AsRef < [ u8 ] > for KeccakPermutationState {
29+ fn as_ref ( & self ) -> & [ u8 ] {
30+ self . 0 . as_bytes ( )
5531 }
32+ }
5633
57- pub fn permute ( & mut self ) {
58- let mut flat = self . bytes_to_flat_state ( ) ;
59- keccakf ( & mut flat) ;
60- self . flat_state_to_bytes ( flat) ;
34+ impl AsMut < [ u8 ] > for KeccakPermutationState {
35+ fn as_mut ( & mut self ) -> & mut [ u8 ] {
36+ self . 0 . as_mut_bytes ( )
6137 }
6238}
6339
6440/// Duplex sponge construction using Keccak-f[1600].
6541#[ derive( Clone ) ]
6642pub struct KeccakDuplexSponge {
67- pub state : KeccakPermutationState ,
68- pub rate : usize ,
69- pub capacity : usize ,
43+ state : KeccakPermutationState ,
7044 absorb_index : usize ,
7145 squeeze_index : usize ,
7246}
7347
7448impl KeccakDuplexSponge {
75- pub fn new ( iv : & [ u8 ] ) -> Self {
76- assert_eq ! ( iv. len( ) , 32 ) ;
77-
78- let state = KeccakPermutationState :: new ( iv. try_into ( ) . unwrap ( ) ) ;
79- let rate = R ;
80- let capacity = N - R ;
49+ pub fn new ( iv : [ u8 ; 32 ] ) -> Self {
50+ let state = KeccakPermutationState :: new ( iv) ;
8151 KeccakDuplexSponge {
8252 state,
83- rate,
84- capacity,
8553 absorb_index : 0 ,
86- squeeze_index : rate ,
54+ squeeze_index : RATE ,
8755 }
8856 }
8957}
9058
9159impl DuplexSpongeInterface for KeccakDuplexSponge {
92- fn new ( iv : & [ u8 ] ) -> Self {
60+ fn new ( iv : [ u8 ; 32 ] ) -> Self {
9361 KeccakDuplexSponge :: new ( iv)
9462 }
9563
9664 fn absorb ( & mut self , mut input : & [ u8 ] ) {
97- self . squeeze_index = self . rate ;
65+ self . squeeze_index = RATE ;
9866
9967 while !input. is_empty ( ) {
100- if self . absorb_index == self . rate {
68+ if self . absorb_index == RATE {
10169 self . state . permute ( ) ;
10270 self . absorb_index = 0 ;
10371 }
10472
105- let chunk_size = usize:: min ( self . rate - self . absorb_index , input. len ( ) ) ;
106- let dest = & mut self . state . state [ self . absorb_index ..self . absorb_index + chunk_size] ;
73+ let chunk_size = usize:: min ( RATE - self . absorb_index , input. len ( ) ) ;
74+ let dest = & mut self . state . as_mut ( ) [ self . absorb_index ..self . absorb_index + chunk_size] ;
10775 dest. copy_from_slice ( & input[ ..chunk_size] ) ;
10876 self . absorb_index += chunk_size;
10977 input = & input[ chunk_size..] ;
11078 }
11179 }
11280
11381 fn squeeze ( & mut self , mut length : usize ) -> Vec < u8 > {
114- self . absorb_index = self . rate ;
82+ self . absorb_index = RATE ;
11583
11684 let mut output = Vec :: new ( ) ;
11785 while length != 0 {
118- if self . squeeze_index == self . rate {
86+ if self . squeeze_index == RATE {
11987 self . state . permute ( ) ;
12088 self . squeeze_index = 0 ;
12189 }
12290
123- let chunk_size = usize:: min ( self . rate - self . squeeze_index , length) ;
91+ let chunk_size = usize:: min ( RATE - self . squeeze_index , length) ;
12492 output. extend_from_slice (
125- & self . state . state [ self . squeeze_index ..self . squeeze_index + chunk_size] ,
93+ & self . state . as_mut ( ) [ self . squeeze_index ..self . squeeze_index + chunk_size] ,
12694 ) ;
12795 self . squeeze_index += chunk_size;
12896 length -= chunk_size;
@@ -131,3 +99,20 @@ impl DuplexSpongeInterface for KeccakDuplexSponge {
13199 output
132100 }
133101}
102+
103+ #[ cfg( test) ]
104+ mod tests {
105+ use super :: * ;
106+ use crate :: duplex_sponge:: DuplexSpongeInterface ;
107+
108+ #[ test]
109+ fn test_keccak_duplex_sponge ( ) {
110+ let mut sponge = KeccakDuplexSponge :: new ( [ 0u8 ; 32 ] ) ;
111+
112+ let input = b"Hello, World!" ;
113+ sponge. absorb ( input) ;
114+ let output = sponge. squeeze ( 64 ) ;
115+
116+ assert_eq ! ( output, hex:: decode( "30b74a98221dd643d0814095c212d663a67945c6a582ef8f71bd2a14607ebade3f16e5975ad13d313d9aa0aa97ad29f7df5cff249fa633d3a7ac70d8587bec90" ) . unwrap( ) ) ;
117+ }
118+ }
0 commit comments