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