@@ -79,13 +79,12 @@ impl DuplexSpongeInterface for KeccakDuplexSponge {
7979 }
8080
8181 fn squeeze ( & mut self , mut length : usize ) -> Vec < u8 > {
82- self . absorb_index = RATE ;
83-
8482 let mut output = Vec :: new ( ) ;
8583 while length != 0 {
8684 if self . squeeze_index == RATE {
8785 self . state . permute ( ) ;
8886 self . squeeze_index = 0 ;
87+ self . absorb_index = 0 ;
8988 }
9089
9190 let chunk_size = usize:: min ( RATE - self . squeeze_index , length) ;
@@ -95,7 +94,6 @@ impl DuplexSpongeInterface for KeccakDuplexSponge {
9594 self . squeeze_index += chunk_size;
9695 length -= chunk_size;
9796 }
98-
9997 output
10098 }
10199}
@@ -104,15 +102,112 @@ impl DuplexSpongeInterface for KeccakDuplexSponge {
104102mod tests {
105103 use super :: * ;
106104 use crate :: duplex_sponge:: DuplexSpongeInterface ;
105+ use hex_literal:: hex;
106+
107+ fn assert_sponge_output ( tag : & [ u8 ; 32 ] , input : & [ u8 ] , expected : & [ u8 ] ) {
108+ let mut sponge = KeccakDuplexSponge :: new ( * tag) ;
109+ sponge. absorb ( input) ;
110+ let output = sponge. squeeze ( expected. len ( ) ) ;
111+ assert_eq ! ( output, expected) ;
112+ }
113+
114+ const TEST_TAG : & [ u8 ; 32 ] = b"unit_tests_keccak_tag___________" ;
115+ const HELLO_WORLD_OUTPUT : & [ u8 ] = & hex ! ( "73e4a040a956f57693fb2b2dde8a8ea2c14d39ff8830060cd0301d6de25b2097ba858efedeeb89368eaf7c94a68f62835f932b5f0dd0ba376c48a0fdb5e21f0c" ) ;
107116
108117 #[ test]
109118 fn test_keccak_duplex_sponge ( ) {
110- let mut sponge = KeccakDuplexSponge :: new ( [ 0u8 ; 32 ] ) ;
119+ assert_sponge_output ( TEST_TAG , b"Hello, World!" , HELLO_WORLD_OUTPUT ) ;
120+ }
111121
112- let input = b"Hello, World!" ;
113- sponge. absorb ( input) ;
114- let output = sponge. squeeze ( 64 ) ;
122+ #[ test]
123+ fn test_absorb_empty_before_does_not_break ( ) {
124+ let mut sponge = KeccakDuplexSponge :: new ( * TEST_TAG ) ;
125+ sponge. absorb ( b"" ) ;
126+ sponge. absorb ( b"Hello, World!" ) ;
127+ sponge. squeeze ( 0 ) ;
128+ assert_eq ! ( sponge. squeeze( 64 ) , HELLO_WORLD_OUTPUT ) ;
129+ }
130+ #[ test]
131+ fn test_absorb_empty_after_does_not_break ( ) {
132+ let mut sponge = KeccakDuplexSponge :: new ( * TEST_TAG ) ;
133+ sponge. absorb ( b"Hello, World!" ) ;
134+ sponge. absorb ( b"" ) ;
135+ sponge. squeeze ( 0 ) ;
136+ assert_eq ! ( sponge. squeeze( 64 ) , HELLO_WORLD_OUTPUT ) ;
137+ }
138+
139+ #[ test]
140+ fn test_squeeze_zero_before_behavior ( ) {
141+ let mut sponge = KeccakDuplexSponge :: new ( * TEST_TAG ) ;
142+ sponge. squeeze ( 0 ) ;
143+ sponge. absorb ( b"Hello, World!" ) ;
144+ assert_eq ! ( sponge. squeeze( 64 ) , HELLO_WORLD_OUTPUT ) ;
145+ }
146+
147+ #[ test]
148+ fn test_squeeze_zero_after_behavior ( ) {
149+ let mut sponge = KeccakDuplexSponge :: new ( * TEST_TAG ) ;
150+ sponge. absorb ( b"Hello, World!" ) ;
151+ sponge. squeeze ( 0 ) ;
152+ assert_eq ! ( sponge. squeeze( 64 ) , HELLO_WORLD_OUTPUT ) ;
153+ }
154+
155+ #[ test]
156+ fn test_absorb_squeeze_absorb_consistency ( ) {
157+ let tag = * b"edge-case-test-domain-absorb0000" ;
158+
159+ let mut sponge = KeccakDuplexSponge :: new ( tag) ;
160+ sponge. absorb ( b"first" ) ;
161+ sponge. squeeze ( 32 ) ;
162+ sponge. absorb ( b"second" ) ;
163+ let output = sponge. squeeze ( 32 ) ;
164+
165+ assert_eq ! (
166+ output,
167+ hex!( "20ce6da64ffc09df8de254222c068358da39d23ec43e522ceaaa1b82b90c8b9a" )
168+ ) ;
169+ }
170+ #[ test]
171+ fn test_associativity_of_absorb ( ) {
172+ let expected_output =
173+ hex ! ( "7dfada182d6191e106ce287c2262a443ce2fb695c7cc5037a46626e88889af58" ) ;
174+ let tag = * b"absorb-associativity-domain-----" ;
175+
176+ // Absorb all at once
177+ let mut sponge1 = KeccakDuplexSponge :: new ( tag) ;
178+ sponge1. absorb ( b"hello world" ) ;
179+ let out1 = sponge1. squeeze ( 32 ) ;
180+
181+ // Absorb in two parts
182+ let mut sponge2 = KeccakDuplexSponge :: new ( tag) ;
183+ sponge2. absorb ( b"hello" ) ;
184+ sponge2. absorb ( b" world" ) ;
185+ let out2 = sponge2. squeeze ( 32 ) ;
186+
187+ assert_eq ! ( out1, expected_output) ;
188+ assert_eq ! ( out2, expected_output) ;
189+ }
115190
116- assert_eq ! ( output, hex:: decode( "30b74a98221dd643d0814095c212d663a67945c6a582ef8f71bd2a14607ebade3f16e5975ad13d313d9aa0aa97ad29f7df5cff249fa633d3a7ac70d8587bec90" ) . unwrap( ) ) ;
191+ #[ test]
192+ fn test_tag_affects_output ( ) {
193+ assert_sponge_output (
194+ b"domain-one-differs-here-00000000" ,
195+ b"input" ,
196+ & hex ! ( "2ecad63584ec0ff7f31edb822530762e5cb4b7dc1a62b1ffe02c43f3073a61b8" ) ,
197+ ) ;
198+ assert_sponge_output (
199+ b"domain-two-differs-here-00000000" ,
200+ b"input" ,
201+ & hex ! ( "6310fa0356e1bab0442fa19958e1c4a6d1dcc565b2b139b6044d1a809f531825" ) ,
202+ ) ;
203+ }
204+
205+ #[ test]
206+ fn test_multiple_blocks_absorb_squeeze ( ) {
207+ assert_sponge_output (
208+ b"multi-block-absorb-test_________" ,
209+ & vec ! [ 0xABu8 ; 3 * 200 ] ,
210+ & hex ! ( "606310f839e763f4f37ce4c9730da92d4d293109de06abee8a7b40577125bcbfca331b97aee104d03139247e801d8b1a5f6b028b8e51fd643de790416819780a1235357db153462f78c150e34f29a303288f07f854e229aed41c786313119a1cee87402006ab5102271576542e5580be1927af773b0f1b46ce5c78c15267d3729928909192ea0115fcb9475b38a1ff5004477bbbb1b1f5c6a5c90c29b245a83324cb108133efc82216d33da9866051d93baab3bdf0fe02b007d4eb94885a42fcd02a9acdd47b71b6eeac17f5946367d6c69c95cbb80ac91d75e22c9862cf5fe10c7e121368e8a8cd9ff8eebe21071ff014e053725bcc624cd9f31818c4d049e70c14a22e5d3062a553ceca6157315ef2bdb3619c970c9c3d60817ee68291dcd17a282ed1b33cb3afb79c8247cd46de13add88da4418278c8b6b919914be5379daa823b036da008718c1d2a4a0768ecdf032e2b93c344ff65768c8a383a8747a1dcc13b5569b4e15cab9cc8f233fb28b13168284c8a998be6f8fa05389ff9c1d90c5845060d2df3fe0a923be8603abbd2b6f6dd6a5c09c81afe7c06bec789db87185297d6f7261f1e5637f2d140ff3b306df77f42cceffe769545ea8b011022387cd9e3d4f2c97feff5099139715f72301799fcfd59aa30f997e26da9eb7d86ee934a3f9c116d4a9e1012d795db35e1c61d27cd74bb6002f463fc129c1f9c4f25bc8e79c051ac2f1686e393d670f8d1e4cea12acfbff5a135623615d69a88f390569f17a0fc65f5886e2df491615155d5c3eb871209a5c7b0439585ad1a0acbede2e1a8d5aad1d8f3a033267e12185c5f2bbab0f2f1769247" ) ,
211+ ) ;
117212 }
118213}
0 commit comments