anemoi/jubjub/anemoi_4_3/
hasher.rs1#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5
6use super::digest::AnemoiDigest;
7use super::{Jive, Sponge};
8use super::{DIGEST_SIZE, NUM_COLUMNS, RATE_WIDTH, STATE_WIDTH};
9use crate::jubjub::anemoi_4_3::AnemoiJubjub_4_3;
10use crate::traits::Anemoi;
11use ark_ff::PrimeField;
12
13use super::Felt;
14use super::{One, Zero};
15
16impl Sponge<Felt> for AnemoiJubjub_4_3 {
17 type Digest = AnemoiDigest;
18
19 fn hash(bytes: &[u8]) -> Self::Digest {
20 let num_elements = if bytes.len() % 31 == 0 {
23 bytes.len() / 31
24 } else {
25 bytes.len() / 31 + 1
26 };
27
28 let sigma = if num_elements % RATE_WIDTH == 0 {
29 Felt::one()
30 } else {
31 Felt::zero()
32 };
33
34 let mut state = [Felt::zero(); STATE_WIDTH];
36
37 let mut i = 0;
44 let mut num_hashed = 0;
45 let mut buf = [0u8; 32];
46 for chunk in bytes.chunks(31) {
47 if num_hashed + i < num_elements - 1 {
48 buf[..31].copy_from_slice(chunk);
49 } else {
50 let chunk_len = chunk.len();
54 buf = [0u8; 32];
55 buf[..chunk_len].copy_from_slice(chunk);
56 if chunk_len < 31 {
58 buf[chunk_len] = 1;
59 }
60 }
61
62 state[i] += Felt::from_le_bytes_mod_order(&buf[..]);
66 i += 1;
67 if i % RATE_WIDTH == 0 {
68 AnemoiJubjub_4_3::permutation(&mut state);
69 i = 0;
70 num_hashed += RATE_WIDTH;
71 }
72 }
73
74 state[STATE_WIDTH - 1] += sigma;
76
77 if sigma.is_zero() {
83 state[i] += Felt::one();
84 AnemoiJubjub_4_3::permutation(&mut state);
85 }
86
87 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
91 }
92
93 fn hash_field(elems: &[Felt]) -> Self::Digest {
94 let mut state = [Felt::zero(); STATE_WIDTH];
96
97 let sigma = if elems.len() % RATE_WIDTH == 0 {
98 Felt::one()
99 } else {
100 Felt::zero()
101 };
102
103 let mut i = 0;
104 for &element in elems.iter() {
105 state[i] += element;
106 i += 1;
107 if i % RATE_WIDTH == 0 {
108 AnemoiJubjub_4_3::permutation(&mut state);
109 i = 0;
110 }
111 }
112
113 state[STATE_WIDTH - 1] += sigma;
115
116 if sigma.is_zero() {
122 state[i] += Felt::one();
123 AnemoiJubjub_4_3::permutation(&mut state);
124 }
125
126 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
129 }
130
131 fn merge(digests: &[Self::Digest; 2]) -> Self::Digest {
132 let mut state = [Felt::zero(); STATE_WIDTH];
134
135 state[0..DIGEST_SIZE].copy_from_slice(digests[0].as_elements());
138 state[DIGEST_SIZE..2 * DIGEST_SIZE].copy_from_slice(digests[0].as_elements());
139
140 AnemoiJubjub_4_3::permutation(&mut state);
142
143 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
144 }
145}
146
147impl Jive<Felt> for AnemoiJubjub_4_3 {
148 fn compress(elems: &[Felt]) -> Vec<Felt> {
149 assert!(elems.len() == STATE_WIDTH);
150
151 let mut state = elems.to_vec();
152 AnemoiJubjub_4_3::permutation(&mut state);
153
154 let mut result = [Felt::zero(); NUM_COLUMNS];
155 for (i, r) in result.iter_mut().enumerate() {
156 *r = elems[i] + elems[i + NUM_COLUMNS] + state[i] + state[i + NUM_COLUMNS];
157 }
158
159 result.to_vec()
160 }
161
162 fn compress_k(elems: &[Felt], k: usize) -> Vec<Felt> {
163 assert!(elems.len() == STATE_WIDTH);
164 assert!(STATE_WIDTH % k == 0);
165 assert!(k % 2 == 0);
166
167 let mut state = elems.to_vec();
168 AnemoiJubjub_4_3::permutation(&mut state);
169
170 let mut result = vec![Felt::zero(); STATE_WIDTH / k];
171 let c = result.len();
172 for (i, r) in result.iter_mut().enumerate() {
173 for j in 0..k {
174 *r += elems[i + c * j] + state[i + c * j];
175 }
176 }
177
178 result
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 #[cfg(not(feature = "std"))]
185 use alloc::vec;
186
187 use super::super::MontFp;
188 use super::*;
189 use ark_ff::BigInteger;
190
191 #[test]
192 fn test_anemoi_hash() {
193 let input_data = [
195 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
196 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
197 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
198 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
199 vec![MontFp!(
200 "19736911815663382719237239115786888395575970607072582643439733400861889127809"
201 )],
202 vec![
203 MontFp!(
204 "31946759962175780374941261532958277798312448517961548858630877527765960894665"
205 ),
206 MontFp!(
207 "31680178724577489535529906488875063813014417633893660210126505779894153150302"
208 ),
209 ],
210 vec![
211 MontFp!(
212 "15100074709805963566161313617893289450863920634620118918341174303450723706505"
213 ),
214 MontFp!(
215 "26991075841797048094523911515386779089616660122394275435269652583647141162643"
216 ),
217 MontFp!(
218 "23761055101505274891261696792444779377068885548604844277573549011731223771684"
219 ),
220 ],
221 vec![
222 MontFp!(
223 "32105594753131030823905475653352743335424796763733160951166436046612010717055"
224 ),
225 MontFp!(
226 "24796431536350598774278045145436006634601298982968352798234443773996100888040"
227 ),
228 MontFp!(
229 "42548285289754577520238386221339202252725381906857009731131609145529353643750"
230 ),
231 MontFp!(
232 "51832059921719748524500148445537616852277071433800155947397646863193952240863"
233 ),
234 ],
235 vec![
236 MontFp!(
237 "1685287177962010948634847020397702753124281625366799951519105194053598124989"
238 ),
239 MontFp!(
240 "20174147333400258966356845230019322112808487184590891010553884228507683189189"
241 ),
242 MontFp!(
243 "42579515684805859653403026523244442411111597245467147557668580096906060147633"
244 ),
245 MontFp!(
246 "18464889611763124528088774889057062981994008860698292684284800102206531642091"
247 ),
248 MontFp!(
249 "27939464771368012549844909928951309357193379363471123307137671121916994869588"
250 ),
251 ],
252 vec![
253 MontFp!(
254 "26288506374337233237831346805552604438156800874545969417895226312740793936092"
255 ),
256 MontFp!(
257 "52134314164669899271836981617482339351659104456898310695906629048366557554107"
258 ),
259 MontFp!(
260 "11952069606878620857447002269771042274909344717517619770517608485610969643597"
261 ),
262 MontFp!(
263 "12708257021021527694474435639668406076795082041062708643824131522456656513197"
264 ),
265 MontFp!(
266 "35510257625349750875854515723154755203101510280155377118503587497338324056732"
267 ),
268 MontFp!(
269 "22119213328391132574776266432746305056001872591008623325677435512301778001010"
270 ),
271 ],
272 ];
273
274 let output_data = [
275 [MontFp!(
276 "38310213048643262329622760360212489938704092112371866787594917193813139289809"
277 )],
278 [MontFp!(
279 "45147274098615966749487358174073372009888068879405542868378683891398912045625"
280 )],
281 [MontFp!(
282 "4785849960602933515566711981483873501178725314523130166590869761297475734119"
283 )],
284 [MontFp!(
285 "1486774069014101020044227815788714221463930175285233978152612010420134052123"
286 )],
287 [MontFp!(
288 "4172618539027921782691550244087389997928769737233915647018981169427679869727"
289 )],
290 [MontFp!(
291 "49986636652664727166440151191423871759052762592624834821825260055659041109954"
292 )],
293 [MontFp!(
294 "40142577054204156778386279699310575662455349467901388696701183353591683853662"
295 )],
296 [MontFp!(
297 "40870542921816677783831683071896086844665133372200530165396327582519465382607"
298 )],
299 [MontFp!(
300 "3972329888537329495228388652202562079959194676217386210995554592077488684413"
301 )],
302 [MontFp!(
303 "33786031787078512059780857959220183841291296052236835108016737551805429129482"
304 )],
305 ];
306
307 for (input, expected) in input_data.iter().zip(output_data) {
308 assert_eq!(expected, AnemoiJubjub_4_3::hash_field(input).to_elements());
309 }
310 }
311
312 #[test]
313 fn test_anemoi_hash_bytes() {
314 let input_data = [
316 vec![Felt::zero(); 4],
317 vec![Felt::one(); 4],
318 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
319 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
320 ];
321
322 let output_data = [
323 [MontFp!(
324 "38310213048643262329622760360212489938704092112371866787594917193813139289809"
325 )],
326 [MontFp!(
327 "45147274098615966749487358174073372009888068879405542868378683891398912045625"
328 )],
329 [MontFp!(
330 "4785849960602933515566711981483873501178725314523130166590869761297475734119"
331 )],
332 [MontFp!(
333 "1486774069014101020044227815788714221463930175285233978152612010420134052123"
334 )],
335 ];
336
337 for (input, expected) in input_data.iter().zip(output_data) {
341 let mut bytes = [0u8; 124];
342 bytes[0..31].copy_from_slice(&input[0].into_bigint().to_bytes_le()[0..31]);
343 bytes[31..62].copy_from_slice(&input[1].into_bigint().to_bytes_le()[0..31]);
344 bytes[62..93].copy_from_slice(&input[2].into_bigint().to_bytes_le()[0..31]);
345 bytes[93..124].copy_from_slice(&input[3].into_bigint().to_bytes_le()[0..31]);
346
347 assert_eq!(expected, AnemoiJubjub_4_3::hash(&bytes).to_elements());
348 }
349 }
350
351 #[test]
352 fn test_anemoi_jive() {
353 let input_data = [
355 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
356 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
357 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
358 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
359 ];
360
361 let output_data = [
362 [
363 MontFp!(
364 "48136361849153243738173322980436308194640949106271265019940984579279517354580"
365 ),
366 MontFp!(
367 "49817329994699533652293260449422143653559101821826781651581903522052933662147"
368 ),
369 ],
370 [
371 MontFp!(
372 "18205127879525878941786319451857577932430192362546047236582468460825047231827"
373 ),
374 MontFp!(
375 "21453885597127632191822341381145144602006860020065635625097486765368206615492"
376 ),
377 ],
378 [
379 MontFp!(
380 "48653614180029901857167901490666718526822512985869211183802509495387476230804"
381 ),
382 MontFp!(
383 "13120598758059651227508017984124942960292547395955043822203068042983899773744"
384 ),
385 ],
386 [
387 MontFp!(
388 "16106234441029043570369654455645100385516059460850491304710352948623471075628"
389 ),
390 MontFp!(
391 "12480629909892753583280577597892300648448114904435781136420871444940482192828"
392 ),
393 ],
394 ];
395
396 for (input, expected) in input_data.iter().zip(output_data) {
397 assert_eq!(expected.to_vec(), AnemoiJubjub_4_3::compress(input));
398 }
399
400 for (input, expected) in input_data.iter().zip(output_data) {
401 assert_eq!(expected.to_vec(), AnemoiJubjub_4_3::compress_k(input, 2));
402 }
403
404 let input_data = [
405 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
406 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
407 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
408 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
409 ];
410
411 let output_data = [
412 [MontFp!(
413 "45517816668726586911018842921672486010509498427570408848919229401393869832214"
414 )],
415 [MontFp!(
416 "39659013476653511133608660833002722534437052382611682861679955226193253847319"
417 )],
418 [MontFp!(
419 "9338337762963362605228178966605695649424507881296617183401918838432794820035"
420 )],
421 [MontFp!(
422 "28586864350921797153650232053537401033964174365286272441131224393563953268456"
423 )],
424 ];
425
426 for (input, expected) in input_data.iter().zip(output_data) {
427 assert_eq!(expected.to_vec(), AnemoiJubjub_4_3::compress_k(input, 4));
428 }
429 }
430}