1#![cfg_attr(not(feature = "std"), no_std)]
21#![allow(warnings)]
23#![deny(missing_docs)]
24#[cfg(test)]
25extern crate std;
26
27#[cfg(any(not(feature = "std"), target_has_atomic = "ptr"))]
28#[doc(hidden)]
29extern crate alloc;
30
31pub mod commitment;
32pub mod crhf;
33#[cfg(feature = "gadgets")]
34pub mod gadgets;
35pub mod prf;
36mod rescue_constants;
37pub mod sponge;
38
39use ark_crypto_primitives::sponge::Absorb;
40use ark_ff::{PrimeField, Zero};
41use ark_std::{string::String, vec, vec::Vec};
42use displaydoc::Display;
43
44#[derive(Debug, Display, Eq, PartialEq)]
46pub enum RescueError {
47 ParameterError(String),
49}
50
51impl ark_std::error::Error for RescueError {}
52
53pub const STATE_SIZE: usize = 4;
55pub const CRHF_RATE: usize = 3;
57
58pub const ROUNDS: usize = 12;
100
101pub trait RescueParameter: PrimeField + Absorb {
103 const A: u64;
105 const A_INV: &'static [u64];
107 const MDS_LE: [[&'static [u8]; STATE_SIZE]; STATE_SIZE];
109 const INIT_VEC_LE: [&'static [u8]; STATE_SIZE];
111 const KEY_INJECTION_LE: [[&'static [u8]; 4]; 2 * ROUNDS];
113 const PERMUTATION_ROUND_KEYS: [[&'static [u8]; 4]; 25];
115}
116
117#[derive(Clone, Debug, Eq, PartialEq, Copy, Default)]
118pub struct RescueVector<F> {
120 pub(crate) vec: [F; STATE_SIZE],
121}
122
123impl<F: PrimeField> RescueVector<F> {
125 pub fn zero() -> RescueVector<F> {
127 RescueVector {
128 vec: [F::zero(); STATE_SIZE],
129 }
130 }
131
132 pub fn elems(&self) -> Vec<F> {
135 self.vec.to_vec()
136 }
137
138 pub fn linear(&mut self, matrix: &RescueMatrix<F>, vector: &RescueVector<F>) {
141 let mut aux = matrix.mul_vec(self);
142 aux.add_assign(vector);
143 *self = aux
144 }
145}
146
147impl<F: PrimeField> RescueVector<F> {
149 fn from_elems_le_bytes(e0: &[u8], e1: &[u8], e2: &[u8], e3: &[u8]) -> RescueVector<F> {
150 RescueVector {
151 vec: [
152 F::from_le_bytes_mod_order(e0),
153 F::from_le_bytes_mod_order(e1),
154 F::from_le_bytes_mod_order(e2),
155 F::from_le_bytes_mod_order(e3),
156 ],
157 }
158 }
159
160 fn pow(&mut self, exp: &[u64]) {
161 self.vec.iter_mut().for_each(|elem| {
162 *elem = elem.pow(exp);
163 });
164 }
165
166 fn add_assign(&mut self, vector: &RescueVector<F>) {
167 for (a, b) in self.vec.iter_mut().zip(vector.vec.iter()) {
168 a.add_assign(b);
169 }
170 }
171
172 fn add(&self, vector: &RescueVector<F>) -> RescueVector<F> {
173 let mut aux = *self;
174 aux.add_assign(vector);
175 aux
176 }
177
178 fn add_assign_elems(&mut self, elems: &[F]) {
179 self.vec
180 .iter_mut()
181 .zip(elems.iter())
182 .for_each(|(a, b)| a.add_assign(b));
183 }
184
185 fn dot_product(&self, vector: &RescueVector<F>) -> F {
186 let mut r = F::zero();
187 for (a, b) in self.vec.iter().zip(vector.vec.iter()) {
188 r.add_assign(&a.mul(b));
189 }
190 r
191 }
192}
193
194impl<F: RescueParameter> RescueVector<F> {
195 pub fn non_linear(&mut self, matrix: &RescueMatrix<F>, vector: &RescueVector<F>) {
198 let mut self_aux = *self;
199 self_aux.pow(&[F::A]);
200 let mut aux = matrix.mul_vec(&self_aux);
201 aux.add_assign(vector);
202 *self = aux;
203 }
204}
205
206impl<F: Copy> From<&[F]> for RescueVector<F> {
207 fn from(field_elems: &[F]) -> RescueVector<F> {
208 assert_eq!(field_elems.len(), STATE_SIZE);
209 RescueVector {
210 vec: [
211 field_elems[0],
212 field_elems[1],
213 field_elems[2],
214 field_elems[3],
215 ],
216 }
217 }
218}
219
220impl<F: Copy> From<&[F; STATE_SIZE]> for RescueVector<F> {
221 fn from(field_elems: &[F; STATE_SIZE]) -> RescueVector<F> {
222 RescueVector { vec: *field_elems }
223 }
224}
225
226#[derive(Debug, Clone)]
228pub struct RescueMatrix<F> {
229 matrix: [RescueVector<F>; STATE_SIZE],
230}
231
232impl<F: PrimeField> From<&[RescueVector<F>; STATE_SIZE]> for RescueMatrix<F> {
233 fn from(vectors: &[RescueVector<F>; STATE_SIZE]) -> Self {
234 Self { matrix: *vectors }
235 }
236}
237
238impl<F: PrimeField> RescueMatrix<F> {
239 fn mul_vec(&self, vector: &RescueVector<F>) -> RescueVector<F> {
240 let mut result = [F::zero(); STATE_SIZE];
241 self.matrix
242 .iter()
243 .enumerate()
244 .for_each(|(i, row)| result[i] = row.dot_product(vector));
245 RescueVector { vec: result }
246 }
247
248 pub fn vec(&self, i: usize) -> RescueVector<F> {
252 self.matrix[i]
253 }
254
255 pub fn is_empty(&self) -> bool {
257 self.matrix.is_empty()
258 }
259
260 pub fn len(&self) -> usize {
262 self.matrix.len()
263 }
264}
265
266#[derive(Debug, Clone)]
275#[allow(clippy::upper_case_acronyms)]
276pub struct PRP<F> {
278 mds: RescueMatrix<F>, init_vec: RescueVector<F>, key_injection: Vec<RescueVector<F>>, }
283
284impl<F: RescueParameter> Default for PRP<F> {
285 fn default() -> Self {
286 let mut key_injection = Vec::with_capacity(2 * ROUNDS);
287 for bytes in F::KEY_INJECTION_LE.iter() {
288 key_injection.push(RescueVector::from_elems_le_bytes(
289 bytes[0], bytes[1], bytes[2], bytes[3],
290 ));
291 }
292 PRP {
293 mds: RescueMatrix::from(&[
294 RescueVector::from_elems_le_bytes(
295 F::MDS_LE[0][0],
296 F::MDS_LE[0][1],
297 F::MDS_LE[0][2],
298 F::MDS_LE[0][3],
299 ),
300 RescueVector::from_elems_le_bytes(
301 F::MDS_LE[1][0],
302 F::MDS_LE[1][1],
303 F::MDS_LE[1][2],
304 F::MDS_LE[1][3],
305 ),
306 RescueVector::from_elems_le_bytes(
307 F::MDS_LE[2][0],
308 F::MDS_LE[2][1],
309 F::MDS_LE[2][2],
310 F::MDS_LE[2][3],
311 ),
312 RescueVector::from_elems_le_bytes(
313 F::MDS_LE[3][0],
314 F::MDS_LE[3][1],
315 F::MDS_LE[3][2],
316 F::MDS_LE[3][3],
317 ),
318 ]),
319 init_vec: RescueVector::from_elems_le_bytes(
320 F::INIT_VEC_LE[0],
321 F::INIT_VEC_LE[1],
322 F::INIT_VEC_LE[2],
323 F::INIT_VEC_LE[3],
324 ),
325 key_injection,
326 }
327 }
328}
329
330impl<F: RescueParameter> PRP<F> {
331 pub fn prp(&self, key: &RescueVector<F>, input: &RescueVector<F>) -> RescueVector<F> {
334 let round_keys = self.key_schedule(key);
335 self.prp_with_round_keys(round_keys.as_slice(), input)
336 }
337
338 pub fn prp_with_round_keys(
341 &self,
342 round_keys: &[RescueVector<F>],
343 input: &RescueVector<F>,
344 ) -> RescueVector<F> {
345 assert_eq!(round_keys.len(), 2 * ROUNDS + 1);
346 let mut perm_state = input.add(&round_keys[0]);
347 round_keys[1..].iter().enumerate().for_each(|(round, key)| {
348 if (round % 2).is_zero() {
349 perm_state.pow(F::A_INV);
350 } else {
351 perm_state.pow(&[F::A]);
352 }
353 perm_state.linear(&self.mds, key)
354 });
355 perm_state
356 }
357
358 pub fn key_schedule(&self, key: &RescueVector<F>) -> Vec<RescueVector<F>> {
361 let mut aux = key.add(&self.init_vec);
362 let mut round_keys = vec![aux];
363 (0..2 * ROUNDS).for_each(|i| {
364 let exp = if (i % 2).is_zero() { F::A_INV } else { &[F::A] };
365 aux.pow(exp);
366 aux.linear(&self.mds, &self.key_injection[i]);
367 round_keys.push(aux);
368 });
369 round_keys
370 }
371
372 #[inline]
375 pub fn mds_matrix_ref(&self) -> &RescueMatrix<F> {
376 &self.mds
377 }
378
379 #[inline]
383 pub fn key_injection_vec_ref(&self) -> &[RescueVector<F>] {
384 &self.key_injection
385 }
386
387 #[inline]
390 pub fn init_vec_ref(&self) -> &RescueVector<F> {
391 &self.init_vec
392 }
393}
394
395#[derive(Debug, Clone)]
398pub struct Permutation<F> {
399 rescue_prp: PRP<F>,
400 round_keys: Vec<RescueVector<F>>,
401}
402
403impl<F: RescueParameter> From<PRP<F>> for Permutation<F> {
404 fn from(rescue: PRP<F>) -> Self {
405 let mut keys: Vec<RescueVector<F>> = Vec::with_capacity(2 * ROUNDS + 1);
406 for key in F::PERMUTATION_ROUND_KEYS.iter() {
407 keys.push(RescueVector::from_elems_le_bytes(
408 key[0], key[1], key[2], key[3],
409 ))
410 }
411 Permutation {
412 rescue_prp: rescue,
413 round_keys: keys,
414 }
415 }
416}
417
418impl<F: RescueParameter> Default for Permutation<F> {
419 fn default() -> Self {
420 Permutation::from(PRP::default())
421 }
422}
423
424impl<F: RescueParameter> Permutation<F> {
425 #[inline]
428 pub fn round_keys_ref(&self) -> &[RescueVector<F>] {
429 self.round_keys.as_slice()
430 }
431
432 #[inline]
435 pub fn mds_matrix_ref(&self) -> &RescueMatrix<F> {
436 self.rescue_prp.mds_matrix_ref()
437 }
438 pub fn eval(&self, input: &RescueVector<F>) -> RescueVector<F> {
440 self.rescue_prp
441 .prp_with_round_keys(self.round_keys.as_slice(), input)
442 }
443}
444
445#[cfg(test)]
446mod test_prp {
447 use crate::{RescueVector, PRP};
448 use ark_bls12_377::Fq as Fq377;
449 use ark_bn254::Fq as Fq254;
450 use ark_ed_on_bls12_377::Fq as Fr377;
451 use ark_ed_on_bls12_381::Fq as Fr381;
452 use ark_ed_on_bn254::Fq as Fr254;
453
454 const OUTPUT761: [[u8; 48]; 4] = [
458 [
459 0x37, 0xBE, 0x12, 0x7E, 0xDF, 0x9C, 0xBF, 0xCE, 0x78, 0xE1, 0x4F, 0xEB, 0x69, 0xAC,
460 0x89, 0x53, 0xE7, 0xC4, 0x8D, 0x89, 0x90, 0x77, 0x64, 0x0D, 0xD0, 0x87, 0x42, 0xDD,
461 0x1F, 0x98, 0x30, 0xC8, 0x0F, 0x12, 0x6D, 0x7A, 0x49, 0xD3, 0x22, 0x2E, 0x12, 0xBA,
462 0x5B, 0x0E, 0x29, 0xB7, 0x2C, 0x01,
463 ],
464 [
465 0x68, 0xFE, 0x2E, 0x95, 0x57, 0xDA, 0x2E, 0x36, 0xEC, 0xC1, 0xC5, 0x8A, 0x19, 0x50,
466 0xD7, 0xBE, 0x11, 0x00, 0x3D, 0x5B, 0xAA, 0x8C, 0xF8, 0x45, 0x6F, 0xDC, 0xE4, 0x1F,
467 0xF0, 0x35, 0xC7, 0x62, 0x6A, 0xC2, 0x33, 0xE7, 0x98, 0x9F, 0x26, 0x2A, 0x6E, 0x89,
468 0xD5, 0x43, 0x21, 0xF8, 0x67, 0x01,
469 ],
470 [
471 0x84, 0xB4, 0x93, 0x04, 0x3B, 0x23, 0x3A, 0x1B, 0x43, 0xC3, 0x61, 0x61, 0x1B, 0xA0,
472 0x59, 0xFB, 0x2E, 0x88, 0x76, 0x62, 0x28, 0xBB, 0x32, 0x6F, 0x27, 0x1C, 0xA9, 0xCA,
473 0x60, 0xC1, 0xE0, 0x7A, 0x7D, 0x37, 0x2F, 0x95, 0x75, 0xDD, 0x37, 0x2A, 0x70, 0xD1,
474 0xE4, 0x55, 0xDB, 0x50, 0x2F, 0x00,
475 ],
476 [
477 0x4E, 0x01, 0x9E, 0x8A, 0x7F, 0x6F, 0x3B, 0xDE, 0x7F, 0xF5, 0x58, 0x0B, 0x1A, 0x34,
478 0x95, 0x8D, 0xBC, 0x94, 0x88, 0xD8, 0x5D, 0x25, 0x7A, 0xB0, 0xCC, 0x72, 0xFE, 0x36,
479 0xC3, 0x13, 0xCB, 0x1B, 0x7A, 0x69, 0xCF, 0xCC, 0xAB, 0x2B, 0x55, 0x11, 0x1E, 0xC5,
480 0x7C, 0xFC, 0x47, 0x7D, 0x9D, 0x01,
481 ],
482 ];
483
484 const OUTPUT381: [[u8; 32]; 4] = [
488 [
489 0x12, 0x53, 0x24, 0x66, 0x84, 0xA2, 0x4D, 0x2B, 0xC7, 0x28, 0x3E, 0x0F, 0x80, 0xDF,
490 0x1A, 0xC3, 0x5B, 0xA1, 0xA9, 0x5B, 0x46, 0x60, 0xBD, 0xED, 0xA6, 0xD1, 0x43, 0xB7,
491 0x60, 0xCA, 0x59, 0x0D,
492 ],
493 [
494 0x1B, 0xBE, 0xAB, 0x6C, 0xAB, 0x62, 0xB7, 0xAB, 0x19, 0xDF, 0xFF, 0x4D, 0x73, 0xB5,
495 0x78, 0x30, 0x72, 0xC0, 0xC6, 0xDA, 0x1F, 0x10, 0xAD, 0xD1, 0x28, 0x65, 0xB4, 0x94,
496 0x6F, 0xAC, 0xE5, 0x4B,
497 ],
498 [
499 0x07, 0x86, 0xBD, 0x9A, 0xB3, 0x35, 0x96, 0x22, 0xF0, 0xE5, 0xEA, 0xCC, 0x9C, 0x79,
500 0x89, 0x1F, 0x9D, 0x1D, 0x43, 0x44, 0xCC, 0xA9, 0x9A, 0xB0, 0x0E, 0xC0, 0x57, 0x6B,
501 0x07, 0xF8, 0x53, 0x06,
502 ],
503 [
504 0x9C, 0x23, 0x34, 0xB3, 0x0A, 0xCD, 0x94, 0x11, 0x49, 0xC0, 0x9D, 0x90, 0x7E, 0x7E,
505 0xC8, 0x51, 0x42, 0xD3, 0xCD, 0x5D, 0x05, 0x13, 0x31, 0x66, 0x4D, 0x36, 0x98, 0xCE,
506 0xAC, 0x44, 0x5C, 0x60,
507 ],
508 ];
509 const OUTPUT377: [[u8; 32]; 4] = [
512 [
513 0x65, 0xF2, 0xF2, 0x74, 0x15, 0x7A, 0x5A, 0xB5, 0xE0, 0x86, 0x46, 0x9D, 0xAE, 0x27,
514 0x29, 0xE0, 0x08, 0x39, 0x0D, 0xA6, 0x44, 0x5E, 0x20, 0x76, 0x23, 0x42, 0xDA, 0xF0,
515 0x49, 0xA3, 0x51, 0x02,
516 ],
517 [
518 0x67, 0xB5, 0x6A, 0xBA, 0x4B, 0xB8, 0x0F, 0xE2, 0xFC, 0x3D, 0x7E, 0xFC, 0x70, 0xCA,
519 0x3D, 0x1D, 0xAC, 0xDD, 0xEA, 0x62, 0x81, 0xD7, 0x08, 0x0B, 0x38, 0x5F, 0x0A, 0x68,
520 0xEC, 0xED, 0x53, 0x02,
521 ],
522 [
523 0x10, 0xC5, 0xA0, 0xA1, 0x8E, 0x8D, 0xBC, 0xAD, 0x99, 0xC3, 0xB4, 0xE9, 0x22, 0xC9,
524 0xB1, 0xCF, 0x35, 0x46, 0xE3, 0x52, 0x99, 0x5B, 0xBE, 0x6E, 0x08, 0xFF, 0x4B, 0x2F,
525 0xCE, 0xF0, 0xCB, 0x0A,
526 ],
527 [
528 0x33, 0xB0, 0xD0, 0x58, 0xE9, 0x25, 0x15, 0xB2, 0x8A, 0x9D, 0x16, 0x04, 0xEB, 0x26,
529 0xC4, 0x0E, 0x3F, 0xBF, 0xCF, 0x49, 0x20, 0xA8, 0x89, 0xE2, 0x16, 0x2D, 0x76, 0x19,
530 0xDF, 0x01, 0x02, 0x09,
531 ],
532 ];
533
534 const OUTPUT254: [[u8; 32]; 4] = [
537 [
538 0xDD, 0xE7, 0x55, 0x8E, 0x14, 0xF9, 0x4C, 0xEE, 0x9F, 0xCC, 0xB2, 0x02, 0xFC, 0x0E,
539 0x54, 0x21, 0xF2, 0xAA, 0xB8, 0x48, 0x05, 0xDB, 0x9B, 0x7A, 0xD2, 0x36, 0xA5, 0xF1,
540 0x49, 0x77, 0xB4, 0x17,
541 ],
542 [
543 0x43, 0x5F, 0x99, 0x3C, 0xB7, 0xB3, 0x84, 0x74, 0x4E, 0x80, 0x83, 0xFF, 0x73, 0x20,
544 0x07, 0xD9, 0x7B, 0xEC, 0x4B, 0x90, 0x48, 0x1D, 0xFD, 0x72, 0x4C, 0xF0, 0xA5, 0x7C,
545 0xDC, 0x68, 0xC0, 0x25,
546 ],
547 [
548 0x2C, 0x7B, 0x21, 0x09, 0x9D, 0x10, 0xE9, 0x5C, 0x36, 0x3E, 0x6D, 0x20, 0x28, 0xBB,
549 0xDB, 0x1E, 0xED, 0xF4, 0x22, 0x9B, 0x3A, 0xEE, 0x1E, 0x6F, 0x89, 0x13, 0x3D, 0x1E,
550 0x4C, 0xA0, 0xA6, 0x23,
551 ],
552 [
553 0x25, 0x9B, 0x47, 0xA2, 0x29, 0xFD, 0xC1, 0x08, 0xA9, 0xD1, 0x44, 0x71, 0x15, 0x8A,
554 0x5A, 0x1A, 0x55, 0x5B, 0x88, 0xAE, 0xD6, 0xF6, 0x57, 0xD3, 0x33, 0x07, 0xE1, 0x5B,
555 0x71, 0x5F, 0x12, 0x25,
556 ],
557 ];
558
559 const OUTPUTFQ254: [[u8; 32]; 4] = [
562 [
563 0xC9, 0xAC, 0x42, 0x08, 0x04, 0x18, 0xFC, 0x10, 0xA4, 0x41, 0xF4, 0xF9, 0x06, 0x2B,
564 0xE2, 0x87, 0xB7, 0x7A, 0xC4, 0x65, 0x8C, 0xE0, 0xE9, 0x78, 0xB0, 0x48, 0x39, 0xB6,
565 0x96, 0x9B, 0x60, 0x1B,
566 ],
567 [
568 0x00, 0xC2, 0xF9, 0x07, 0x54, 0x25, 0xF2, 0xC6, 0x75, 0x21, 0x01, 0x14, 0xF6, 0xD1,
569 0xAF, 0xE1, 0x0D, 0xD4, 0xFC, 0xEC, 0x15, 0xF3, 0x7D, 0x9A, 0x91, 0x26, 0x51, 0xDE,
570 0xC8, 0x8A, 0x19, 0x09,
571 ],
572 [
573 0x78, 0xDB, 0xB7, 0xEA, 0xD4, 0x35, 0x5E, 0xED, 0xAE, 0x14, 0xD6, 0xB1, 0xE8, 0x0D,
574 0xB4, 0xA7, 0x29, 0x9B, 0xBA, 0x6F, 0xBD, 0xA4, 0xEB, 0x52, 0x7D, 0xD5, 0x9B, 0x03,
575 0x17, 0x83, 0x06, 0x1D,
576 ],
577 [
578 0x72, 0xC6, 0xB8, 0xF9, 0x9E, 0xF3, 0xDA, 0x20, 0xED, 0x3D, 0xE4, 0x39, 0x87, 0x28,
579 0xE9, 0x25, 0x0D, 0x8D, 0x57, 0xCE, 0xEE, 0xCA, 0x35, 0xFB, 0x8E, 0x7E, 0xE3, 0x32,
580 0xDA, 0x03, 0x3F, 0x1B,
581 ],
582 ];
583
584 #[test]
585 fn test_rescue_perm_on_0_vec() {
586 test_rescue_perm_on_0_vec_fq254();
587 test_rescue_perm_on_0_vec_254();
588 test_rescue_perm_on_0_vec_377();
589 test_rescue_perm_on_0_vec_381();
590 test_rescue_perm_on_0_vec_761();
591 }
592
593 fn test_rescue_perm_on_0_vec_fq254() {
594 let rescue = PRP::<Fq254>::default();
595 let key = RescueVector::zero();
596 let input = RescueVector::zero();
597 let expected = RescueVector::from_elems_le_bytes(
598 &OUTPUTFQ254[0],
599 &OUTPUTFQ254[1],
600 &OUTPUTFQ254[2],
601 &OUTPUTFQ254[3],
602 );
603 let real_output = rescue.prp(&key, &input);
604 let round_keys = rescue.key_schedule(&key);
605
606 let real_output_with_round_keys = rescue.prp_with_round_keys(&round_keys, &input);
607 assert_eq!(real_output, real_output_with_round_keys);
608 assert_eq!(real_output, expected);
609 }
610
611 fn test_rescue_perm_on_0_vec_254() {
612 let rescue = PRP::<Fr254>::default();
613 let key = RescueVector::zero();
614 let input = RescueVector::zero();
615 let expected = RescueVector::from_elems_le_bytes(
616 &OUTPUT254[0],
617 &OUTPUT254[1],
618 &OUTPUT254[2],
619 &OUTPUT254[3],
620 );
621 let real_output = rescue.prp(&key, &input);
622 let round_keys = rescue.key_schedule(&key);
623 let real_output_with_round_keys = rescue.prp_with_round_keys(&round_keys, &input);
624 assert_eq!(real_output, real_output_with_round_keys);
625 assert_eq!(real_output, expected);
626 }
627
628 fn test_rescue_perm_on_0_vec_381() {
629 let rescue = PRP::<Fr381>::default();
630 let key = RescueVector::zero();
631 let input = RescueVector::zero();
632 let expected = RescueVector::from_elems_le_bytes(
633 &OUTPUT381[0],
634 &OUTPUT381[1],
635 &OUTPUT381[2],
636 &OUTPUT381[3],
637 );
638 let real_output = rescue.prp(&key, &input);
639 let round_keys = rescue.key_schedule(&key);
640 let real_output_with_round_keys = rescue.prp_with_round_keys(&round_keys, &input);
641
642 assert_eq!(real_output, real_output_with_round_keys);
643 assert_eq!(real_output, expected);
644 }
645
646 fn test_rescue_perm_on_0_vec_377() {
647 let rescue = PRP::<Fr377>::default();
648 let key = RescueVector::zero();
649 let input = RescueVector::zero();
650 let expected = RescueVector::from_elems_le_bytes(
651 &OUTPUT377[0],
652 &OUTPUT377[1],
653 &OUTPUT377[2],
654 &OUTPUT377[3],
655 );
656 let real_output = rescue.prp(&key, &input);
657 let round_keys = rescue.key_schedule(&key);
658 let real_output_with_round_keys = rescue.prp_with_round_keys(&round_keys, &input);
659 assert_eq!(real_output, real_output_with_round_keys);
660 assert_eq!(real_output, expected);
661 }
662
663 fn test_rescue_perm_on_0_vec_761() {
664 let rescue = PRP::<Fq377>::default();
665 let key = RescueVector::zero();
666 let input = RescueVector::zero();
667 let expected = RescueVector::from_elems_le_bytes(
668 &OUTPUT761[0],
669 &OUTPUT761[1],
670 &OUTPUT761[2],
671 &OUTPUT761[3],
672 );
673 let real_output = rescue.prp(&key, &input);
674 let round_keys = rescue.key_schedule(&key);
675 let real_output_with_round_keys = rescue.prp_with_round_keys(&round_keys, &input);
676 assert_eq!(real_output, real_output_with_round_keys);
677 assert_eq!(real_output, expected);
678 }
679
680 }
703
704#[cfg(test)]
705mod test_permutation {
706 use crate::{crhf::RescueCRHF, Permutation, RescueParameter, RescueVector, PRP};
707 use ark_bls12_377::Fq as Fq377;
708 use ark_bn254::Fq as Fq254;
709 use ark_ed_on_bls12_377::Fq as Fr377;
710 use ark_ed_on_bls12_381::Fq as Fr381;
711 use ark_ed_on_bn254::Fq as Fr254;
712 use ark_ff::PrimeField;
713 use ark_std::{vec, Zero};
714
715 #[test]
716 fn test_round_keys() {
717 test_round_keys_helper::<Fq254>();
718 test_round_keys_helper::<Fr254>();
719 test_round_keys_helper::<Fr377>();
720 test_round_keys_helper::<Fr381>();
721 test_round_keys_helper::<Fq377>();
722 }
723
724 fn test_round_keys_helper<F: RescueParameter>() {
725 let rescue_perm = PRP::<F>::default();
726 let rescue_hash = Permutation::default();
727 let zero = RescueVector::zero();
728 let keys2 = rescue_perm.key_schedule(&zero);
729
730 assert_eq!(rescue_hash.round_keys, keys2);
740 }
741
742 const OUTPUT761: [[u8; 48]; 3] = [
746 [
747 0x37, 0xBE, 0x12, 0x7E, 0xDF, 0x9C, 0xBF, 0xCE, 0x78, 0xE1, 0x4F, 0xEB, 0x69, 0xAC,
748 0x89, 0x53, 0xE7, 0xC4, 0x8D, 0x89, 0x90, 0x77, 0x64, 0x0D, 0xD0, 0x87, 0x42, 0xDD,
749 0x1F, 0x98, 0x30, 0xC8, 0x0F, 0x12, 0x6D, 0x7A, 0x49, 0xD3, 0x22, 0x2E, 0x12, 0xBA,
750 0x5B, 0x0E, 0x29, 0xB7, 0x2C, 0x01,
751 ],
752 [
753 0x68, 0xFE, 0x2E, 0x95, 0x57, 0xDA, 0x2E, 0x36, 0xEC, 0xC1, 0xC5, 0x8A, 0x19, 0x50,
754 0xD7, 0xBE, 0x11, 0x00, 0x3D, 0x5B, 0xAA, 0x8C, 0xF8, 0x45, 0x6F, 0xDC, 0xE4, 0x1F,
755 0xF0, 0x35, 0xC7, 0x62, 0x6A, 0xC2, 0x33, 0xE7, 0x98, 0x9F, 0x26, 0x2A, 0x6E, 0x89,
756 0xD5, 0x43, 0x21, 0xF8, 0x67, 0x01,
757 ],
758 [
759 0x84, 0xB4, 0x93, 0x04, 0x3B, 0x23, 0x3A, 0x1B, 0x43, 0xC3, 0x61, 0x61, 0x1B, 0xA0,
760 0x59, 0xFB, 0x2E, 0x88, 0x76, 0x62, 0x28, 0xBB, 0x32, 0x6F, 0x27, 0x1C, 0xA9, 0xCA,
761 0x60, 0xC1, 0xE0, 0x7A, 0x7D, 0x37, 0x2F, 0x95, 0x75, 0xDD, 0x37, 0x2A, 0x70, 0xD1,
762 0xE4, 0x55, 0xDB, 0x50, 0x2F, 0x00,
763 ],
764 ];
765
766 const OUTPUT254: [[u8; 32]; 3] = [
770 [
771 0xDD, 0xE7, 0x55, 0x8E, 0x14, 0xF9, 0x4C, 0xEE, 0x9F, 0xCC, 0xB2, 0x02, 0xFC, 0x0E,
772 0x54, 0x21, 0xF2, 0xAA, 0xB8, 0x48, 0x05, 0xDB, 0x9B, 0x7A, 0xD2, 0x36, 0xA5, 0xF1,
773 0x49, 0x77, 0xB4, 0x17,
774 ],
775 [
776 0x43, 0x5F, 0x99, 0x3C, 0xB7, 0xB3, 0x84, 0x74, 0x4E, 0x80, 0x83, 0xFF, 0x73, 0x20,
777 0x07, 0xD9, 0x7B, 0xEC, 0x4B, 0x90, 0x48, 0x1D, 0xFD, 0x72, 0x4C, 0xF0, 0xA5, 0x7C,
778 0xDC, 0x68, 0xC0, 0x25,
779 ],
780 [
781 0x2C, 0x7B, 0x21, 0x09, 0x9D, 0x10, 0xE9, 0x5C, 0x36, 0x3E, 0x6D, 0x20, 0x28, 0xBB,
782 0xDB, 0x1E, 0xED, 0xF4, 0x22, 0x9B, 0x3A, 0xEE, 0x1E, 0x6F, 0x89, 0x13, 0x3D, 0x1E,
783 0x4C, 0xA0, 0xA6, 0x23,
784 ],
785 ];
786 const OUTPUT377: [[u8; 32]; 3] = [
790 [
791 0x65, 0xF2, 0xF2, 0x74, 0x15, 0x7A, 0x5A, 0xB5, 0xE0, 0x86, 0x46, 0x9D, 0xAE, 0x27,
792 0x29, 0xE0, 0x08, 0x39, 0x0D, 0xA6, 0x44, 0x5E, 0x20, 0x76, 0x23, 0x42, 0xDA, 0xF0,
793 0x49, 0xA3, 0x51, 0x02,
794 ],
795 [
796 0x67, 0xB5, 0x6A, 0xBA, 0x4B, 0xB8, 0x0F, 0xE2, 0xFC, 0x3D, 0x7E, 0xFC, 0x70, 0xCA,
797 0x3D, 0x1D, 0xAC, 0xDD, 0xEA, 0x62, 0x81, 0xD7, 0x08, 0x0B, 0x38, 0x5F, 0x0A, 0x68,
798 0xEC, 0xED, 0x53, 0x02,
799 ],
800 [
801 0x10, 0xC5, 0xA0, 0xA1, 0x8E, 0x8D, 0xBC, 0xAD, 0x99, 0xC3, 0xB4, 0xE9, 0x22, 0xC9,
802 0xB1, 0xCF, 0x35, 0x46, 0xE3, 0x52, 0x99, 0x5B, 0xBE, 0x6E, 0x08, 0xFF, 0x4B, 0x2F,
803 0xCE, 0xF0, 0xCB, 0x0A,
804 ],
805 ];
806
807 const OUTPUT381: [[u8; 32]; 3] = [
811 [
812 0x12, 0x53, 0x24, 0x66, 0x84, 0xA2, 0x4D, 0x2B, 0xC7, 0x28, 0x3E, 0x0F, 0x80, 0xDF,
813 0x1A, 0xC3, 0x5B, 0xA1, 0xA9, 0x5B, 0x46, 0x60, 0xBD, 0xED, 0xA6, 0xD1, 0x43, 0xB7,
814 0x60, 0xCA, 0x59, 0x0D,
815 ],
816 [
817 0x1B, 0xBE, 0xAB, 0x6C, 0xAB, 0x62, 0xB7, 0xAB, 0x19, 0xDF, 0xFF, 0x4D, 0x73, 0xB5,
818 0x78, 0x30, 0x72, 0xC0, 0xC6, 0xDA, 0x1F, 0x10, 0xAD, 0xD1, 0x28, 0x65, 0xB4, 0x94,
819 0x6F, 0xAC, 0xE5, 0x4B,
820 ],
821 [
822 0x07, 0x86, 0xBD, 0x9A, 0xB3, 0x35, 0x96, 0x22, 0xF0, 0xE5, 0xEA, 0xCC, 0x9C, 0x79,
823 0x89, 0x1F, 0x9D, 0x1D, 0x43, 0x44, 0xCC, 0xA9, 0x9A, 0xB0, 0x0E, 0xC0, 0x57, 0x6B,
824 0x07, 0xF8, 0x53, 0x06,
825 ],
826 ];
827
828 const OUTPUTFQ254: [[u8; 32]; 4] = [
831 [
832 0xC9, 0xAC, 0x42, 0x08, 0x04, 0x18, 0xFC, 0x10, 0xA4, 0x41, 0xF4, 0xF9, 0x06, 0x2B,
833 0xE2, 0x87, 0xB7, 0x7A, 0xC4, 0x65, 0x8C, 0xE0, 0xE9, 0x78, 0xB0, 0x48, 0x39, 0xB6,
834 0x96, 0x9B, 0x60, 0x1B,
835 ],
836 [
837 0x00, 0xC2, 0xF9, 0x07, 0x54, 0x25, 0xF2, 0xC6, 0x75, 0x21, 0x01, 0x14, 0xF6, 0xD1,
838 0xAF, 0xE1, 0x0D, 0xD4, 0xFC, 0xEC, 0x15, 0xF3, 0x7D, 0x9A, 0x91, 0x26, 0x51, 0xDE,
839 0xC8, 0x8A, 0x19, 0x09,
840 ],
841 [
842 0x78, 0xDB, 0xB7, 0xEA, 0xD4, 0x35, 0x5E, 0xED, 0xAE, 0x14, 0xD6, 0xB1, 0xE8, 0x0D,
843 0xB4, 0xA7, 0x29, 0x9B, 0xBA, 0x6F, 0xBD, 0xA4, 0xEB, 0x52, 0x7D, 0xD5, 0x9B, 0x03,
844 0x17, 0x83, 0x06, 0x1D,
845 ],
846 [
847 0x72, 0xC6, 0xB8, 0xF9, 0x9E, 0xF3, 0xDA, 0x20, 0xED, 0x3D, 0xE4, 0x39, 0x87, 0x28,
848 0xE9, 0x25, 0x0D, 0x8D, 0x57, 0xCE, 0xEE, 0xCA, 0x35, 0xFB, 0x8E, 0x7E, 0xE3, 0x32,
849 0xDA, 0x03, 0x3F, 0x1B,
850 ],
851 ];
852
853 #[test]
854 fn test_sponge() {
855 test_sponge_helper::<Fq254>();
856 test_sponge_helper::<Fr254>();
857 test_sponge_helper::<Fr377>();
858 test_sponge_helper::<Fr381>();
859 test_sponge_helper::<Fq377>();
860 }
861
862 fn test_sponge_helper<F: RescueParameter>() {
863 let rescue_prp = PRP::default();
864 let mut prng = jf_utils::test_rng();
865 let e0 = F::rand(&mut prng);
866 let e1 = F::rand(&mut prng);
867 let e2 = F::rand(&mut prng);
868 let e3 = F::rand(&mut prng);
869 let e4 = F::rand(&mut prng);
870 let e5 = F::rand(&mut prng);
871
872 let input = [e0, e1, e2, e3, e4, e5];
873
874 let output = RescueCRHF::<F>::sponge_no_padding(&input, 1).unwrap()[0];
875
876 let zero = RescueVector::zero();
877 let mut state = RescueVector {
878 vec: [input[0], input[1], input[2], F::zero()],
879 };
880 state = rescue_prp.prp(&zero, &state);
881 state.add_assign_elems(&input[3..6]);
882 state = rescue_prp.prp(&zero, &state);
883 assert_eq!(output, state.vec[0]);
884 }
885
886 #[test]
887 fn test_rescue_hash_on_0_vec() {
888 test_rescue_hash_on_0_vec_fq254();
889 test_rescue_hash_on_0_vec_254();
890 test_rescue_hash_on_0_vec_377();
891 test_rescue_hash_on_0_vec_381();
892 test_rescue_hash_on_0_vec_761()
893 }
894
895 fn test_rescue_hash_on_0_vec_fq254() {
896 let input = [Fq254::zero(); 3];
897 let expected = vec![
898 Fq254::from_le_bytes_mod_order(&OUTPUTFQ254[0]),
899 Fq254::from_le_bytes_mod_order(&OUTPUTFQ254[1]),
900 Fq254::from_le_bytes_mod_order(&OUTPUTFQ254[2]),
901 ];
902 let real_output = RescueCRHF::sponge_no_padding(&input, 3).unwrap();
903 assert_eq!(real_output, expected);
904 }
905
906 fn test_rescue_hash_on_0_vec_254() {
907 let input = [Fr254::zero(); 3];
908 let expected = vec![
909 Fr254::from_le_bytes_mod_order(&OUTPUT254[0]),
910 Fr254::from_le_bytes_mod_order(&OUTPUT254[1]),
911 Fr254::from_le_bytes_mod_order(&OUTPUT254[2]),
912 ];
913 let real_output = RescueCRHF::sponge_no_padding(&input, 3).unwrap();
914 assert_eq!(real_output, expected);
915 }
916
917 fn test_rescue_hash_on_0_vec_377() {
918 let input = [Fr377::zero(); 3];
919 let expected = vec![
920 Fr377::from_le_bytes_mod_order(&OUTPUT377[0]),
921 Fr377::from_le_bytes_mod_order(&OUTPUT377[1]),
922 Fr377::from_le_bytes_mod_order(&OUTPUT377[2]),
923 ];
924 let real_output = RescueCRHF::sponge_no_padding(&input, 3).unwrap();
925 assert_eq!(real_output, expected);
926 }
927
928 fn test_rescue_hash_on_0_vec_381() {
929 let input = [Fr381::zero(); 3];
930 let expected = vec![
931 Fr381::from_le_bytes_mod_order(&OUTPUT381[0]),
932 Fr381::from_le_bytes_mod_order(&OUTPUT381[1]),
933 Fr381::from_le_bytes_mod_order(&OUTPUT381[2]),
934 ];
935 let real_output = RescueCRHF::sponge_no_padding(&input, 3).unwrap();
936 assert_eq!(real_output, expected);
937 }
938
939 fn test_rescue_hash_on_0_vec_761() {
940 let input = [Fq377::zero(); 3];
941 let expected = vec![
942 Fq377::from_le_bytes_mod_order(&OUTPUT761[0]),
943 Fq377::from_le_bytes_mod_order(&OUTPUT761[1]),
944 Fq377::from_le_bytes_mod_order(&OUTPUT761[2]),
945 ];
946 let real_output = RescueCRHF::sponge_no_padding(&input, 3).unwrap();
947 assert_eq!(real_output, expected);
948 }
949}