anemoi/pallas/anemoi_4_3/
hasher.rs1#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5
6use super::digest::AnemoiDigest;
7use super::{AnemoiPallas_4_3, Jive, Sponge};
8use super::{DIGEST_SIZE, NUM_COLUMNS, RATE_WIDTH, STATE_WIDTH};
9use crate::traits::Anemoi;
10use ark_ff::PrimeField;
11
12use super::Felt;
13use super::{One, Zero};
14
15impl Sponge<Felt> for AnemoiPallas_4_3 {
16 type Digest = AnemoiDigest;
17
18 fn hash(bytes: &[u8]) -> Self::Digest {
19 let num_elements = if bytes.len() % 31 == 0 {
22 bytes.len() / 31
23 } else {
24 bytes.len() / 31 + 1
25 };
26
27 let sigma = if num_elements % RATE_WIDTH == 0 {
28 Felt::one()
29 } else {
30 Felt::zero()
31 };
32
33 let mut state = [Felt::zero(); STATE_WIDTH];
35
36 let mut i = 0;
43 let mut num_hashed = 0;
44 let mut buf = [0u8; 32];
45 for chunk in bytes.chunks(31) {
46 if num_hashed + i < num_elements - 1 {
47 buf[..31].copy_from_slice(chunk);
48 } else {
49 let chunk_len = chunk.len();
53 buf = [0u8; 32];
54 buf[..chunk_len].copy_from_slice(chunk);
55 if chunk_len < 31 {
57 buf[chunk_len] = 1;
58 }
59 }
60
61 state[i] += Felt::from_le_bytes_mod_order(&buf[..]);
65 i += 1;
66 if i % RATE_WIDTH == 0 {
67 AnemoiPallas_4_3::permutation(&mut state);
68 i = 0;
69 num_hashed += RATE_WIDTH;
70 }
71 }
72
73 state[STATE_WIDTH - 1] += sigma;
75
76 if sigma.is_zero() {
82 state[i] += Felt::one();
83 AnemoiPallas_4_3::permutation(&mut state);
84 }
85
86 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
90 }
91
92 fn hash_field(elems: &[Felt]) -> Self::Digest {
93 let mut state = [Felt::zero(); STATE_WIDTH];
95
96 let sigma = if elems.len() % RATE_WIDTH == 0 {
97 Felt::one()
98 } else {
99 Felt::zero()
100 };
101
102 let mut i = 0;
103 for &element in elems.iter() {
104 state[i] += element;
105 i += 1;
106 if i % RATE_WIDTH == 0 {
107 AnemoiPallas_4_3::permutation(&mut state);
108 i = 0;
109 }
110 }
111
112 state[STATE_WIDTH - 1] += sigma;
114
115 if sigma.is_zero() {
121 state[i] += Felt::one();
122 AnemoiPallas_4_3::permutation(&mut state);
123 }
124
125 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
128 }
129
130 fn merge(digests: &[Self::Digest; 2]) -> Self::Digest {
131 let mut state = [Felt::zero(); STATE_WIDTH];
133
134 state[0..DIGEST_SIZE].copy_from_slice(digests[0].as_elements());
137 state[DIGEST_SIZE..2 * DIGEST_SIZE].copy_from_slice(digests[0].as_elements());
138
139 AnemoiPallas_4_3::permutation(&mut state);
141
142 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
143 }
144}
145
146impl Jive<Felt> for AnemoiPallas_4_3 {
147 fn compress(elems: &[Felt]) -> Vec<Felt> {
148 assert!(elems.len() == STATE_WIDTH);
149
150 let mut state = elems.to_vec();
151 AnemoiPallas_4_3::permutation(&mut state);
152
153 let mut result = [Felt::zero(); NUM_COLUMNS];
154 for (i, r) in result.iter_mut().enumerate() {
155 *r = elems[i] + elems[i + NUM_COLUMNS] + state[i] + state[i + NUM_COLUMNS];
156 }
157
158 result.to_vec()
159 }
160
161 fn compress_k(elems: &[Felt], k: usize) -> Vec<Felt> {
162 assert!(elems.len() == STATE_WIDTH);
163 assert!(STATE_WIDTH % k == 0);
164 assert!(k % 2 == 0);
165
166 let mut state = elems.to_vec();
167 AnemoiPallas_4_3::permutation(&mut state);
168
169 let mut result = vec![Felt::zero(); STATE_WIDTH / k];
170 let c = result.len();
171 for (i, r) in result.iter_mut().enumerate() {
172 for j in 0..k {
173 *r += elems[i + c * j] + state[i + c * j];
174 }
175 }
176
177 result
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 #[cfg(not(feature = "std"))]
184 use alloc::vec;
185
186 use super::super::MontFp;
187 use super::*;
188 use ark_ff::BigInteger;
189
190 #[test]
191 fn test_anemoi_hash() {
192 let input_data = [
194 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
195 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
196 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
197 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
198 vec![MontFp!(
199 "21639214970066534150430088710672344339351825377325572601134230847435855090018"
200 )],
201 vec![
202 MontFp!(
203 "14308310011320271075241074852554551793116589797873291197377178969597814757745"
204 ),
205 MontFp!(
206 "22812519244635639534870240978594413497217364395500311893561032045384117799878"
207 ),
208 ],
209 vec![
210 MontFp!(
211 "23765623204622958643368508730446153544497463659497977322294049803725089680077"
212 ),
213 MontFp!(
214 "2761657738390976099784033013656492009234327105692076199686725552553595160512"
215 ),
216 MontFp!(
217 "12354800733798554344880652102324243621499865971329973211194509884277810483989"
218 ),
219 ],
220 vec![
221 MontFp!(
222 "10033669896525688739559423792041083073657230262399786332112917151491349621156"
223 ),
224 MontFp!(
225 "2402935293599703694925481097313849400153027911079819709951633229930463274411"
226 ),
227 MontFp!(
228 "15141140496634667073241089391482623820656817856452117757862613027185176151320"
229 ),
230 MontFp!(
231 "9230081170729671270782214301227543693465268732972655430727126469580001066836"
232 ),
233 ],
234 vec![
235 MontFp!(
236 "16580475169231560943994826549979368689782367272071060833785390675083215453194"
237 ),
238 MontFp!(
239 "10004412817097373061517532903858807858993405489168929589455000884154966759320"
240 ),
241 MontFp!(
242 "1355194641053070000075197911936524025071372126913817851573375822588356336676"
243 ),
244 MontFp!(
245 "17444611727166347460082061146955620567496772682030127308229081870716301202092"
246 ),
247 MontFp!(
248 "15440790176274981693833551806629298448680841788514608132286069353289615622320"
249 ),
250 ],
251 vec![
252 MontFp!(
253 "15409207566483766714933995237189997770256127690043059752865384785081338806008"
254 ),
255 MontFp!(
256 "5751195299622947836280217965819888862825707754086574762028976072155459214669"
257 ),
258 MontFp!(
259 "804826448337405805732843527912622948408773912073805278584653490742562799174"
260 ),
261 MontFp!(
262 "54411331332446143311253369710064725692225955708390037299651399950515126386"
263 ),
264 MontFp!(
265 "22417573194360036812332079051361603326904698011705537374783188747808796361206"
266 ),
267 MontFp!(
268 "6469054496641404924286933338508030164119881143197330664753674015245329522845"
269 ),
270 ],
271 ];
272
273 let output_data = [
274 [MontFp!(
275 "18667893566940377934413531954661629005239155214336217717980971841120036720992"
276 )],
277 [MontFp!(
278 "16332064307906021858995989073185923369241423502144838929406031304186177756421"
279 )],
280 [MontFp!(
281 "10120813506782340547268980585023925831088423627255340408061228272104188937028"
282 )],
283 [MontFp!(
284 "12573228387563430057694757326408676853111531942075183709320724792995739113307"
285 )],
286 [MontFp!(
287 "21694522994823424510392828412675056114249469142972397236297530118523556182029"
288 )],
289 [MontFp!(
290 "6766589173654963124934839474048684982288045583229496204050981767644297021519"
291 )],
292 [MontFp!(
293 "1842089326709875619803844739111822363096300193007869419513139366580669412870"
294 )],
295 [MontFp!(
296 "5302005038874182146455963492580261694651482438322761024988716317705130000976"
297 )],
298 [MontFp!(
299 "17068290522837623179589332515070046988254553107483674469540861992224659316863"
300 )],
301 [MontFp!(
302 "28627431873786754713714284091089204081618742879828933488615932584482648991866"
303 )],
304 ];
305
306 for (input, expected) in input_data.iter().zip(output_data) {
307 assert_eq!(expected, AnemoiPallas_4_3::hash_field(input).to_elements());
308 }
309 }
310
311 #[test]
312 fn test_anemoi_hash_bytes() {
313 let input_data = [
315 vec![Felt::zero(); 4],
316 vec![Felt::one(); 4],
317 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
318 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
319 ];
320
321 let output_data = [
322 [MontFp!(
323 "18667893566940377934413531954661629005239155214336217717980971841120036720992"
324 )],
325 [MontFp!(
326 "16332064307906021858995989073185923369241423502144838929406031304186177756421"
327 )],
328 [MontFp!(
329 "10120813506782340547268980585023925831088423627255340408061228272104188937028"
330 )],
331 [MontFp!(
332 "12573228387563430057694757326408676853111531942075183709320724792995739113307"
333 )],
334 ];
335
336 for (input, expected) in input_data.iter().zip(output_data) {
340 let mut bytes = [0u8; 124];
341 bytes[0..31].copy_from_slice(&input[0].into_bigint().to_bytes_le()[0..31]);
342 bytes[31..62].copy_from_slice(&input[1].into_bigint().to_bytes_le()[0..31]);
343 bytes[62..93].copy_from_slice(&input[2].into_bigint().to_bytes_le()[0..31]);
344 bytes[93..124].copy_from_slice(&input[3].into_bigint().to_bytes_le()[0..31]);
345
346 assert_eq!(expected, AnemoiPallas_4_3::hash(&bytes).to_elements());
347 }
348 }
349
350 #[test]
351 fn test_anemoi_jive() {
352 let input_data = [
354 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
355 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
356 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
357 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
358 ];
359
360 let output_data = [
361 [
362 MontFp!(
363 "155260004806059969980061416423330881889240336623781546121410760287809104774"
364 ),
365 MontFp!(
366 "18911999830037716111748566585472628944083385984045482994538443407116433259481"
367 ),
368 ],
369 [
370 MontFp!(
371 "10574950278057377054483945886502479610095784600476876759205777595522024326848"
372 ),
373 MontFp!(
374 "878944299778645826471008564793909673728274386951687124423989547665441563258"
375 ),
376 ],
377 [
378 MontFp!(
379 "19987739087819865782694564672591379265397013990789950980715436474624395508317"
380 ),
381 MontFp!(
382 "10174893348081987242771600544387711673877577306100134825491790172317730671617"
383 ),
384 ],
385 [
386 MontFp!(
387 "21195260622338728819653286536837364927496937117816249105425751540779649358326"
388 ),
389 MontFp!(
390 "17916063567746091983605399379505344079993739565625964333895436713994194878281"
391 ),
392 ],
393 ];
394
395 for (input, expected) in input_data.iter().zip(output_data) {
396 assert_eq!(expected.to_vec(), AnemoiPallas_4_3::compress(input));
397 }
398
399 for (input, expected) in input_data.iter().zip(output_data) {
400 assert_eq!(expected.to_vec(), AnemoiPallas_4_3::compress_k(input, 2));
401 }
402
403 let input_data = [
404 vec![Felt::zero(), Felt::zero(), Felt::zero(), Felt::zero()],
405 vec![Felt::one(), Felt::one(), Felt::one(), Felt::one()],
406 vec![Felt::zero(), Felt::zero(), Felt::one(), Felt::one()],
407 vec![Felt::one(), Felt::one(), Felt::zero(), Felt::zero()],
408 ];
409
410 let output_data = [
411 [MontFp!(
412 "19067259834843776081728628001895959825972626320669264540659854167404242364255"
413 )],
414 [MontFp!(
415 "11453894577836022880954954451296389283824058987428563883629767143187465890106"
416 )],
417 [MontFp!(
418 "1214610126572804169573418964807113975911534814948525090252549882592158549597"
419 )],
420 [MontFp!(
421 "10163301880755771947365939664170732044127620201500652723366511490423876606270"
422 )],
423 ];
424
425 for (input, expected) in input_data.iter().zip(output_data) {
426 assert_eq!(expected.to_vec(), AnemoiPallas_4_3::compress_k(input, 4));
427 }
428 }
429}