jf_rescue/permutation.rs
1//! State of a rescue-based, overwrite-mode cryptographic sponge (compliant with
2//! spongefish)
3//!
4//! # Historical note
5//! In 0.2.0 (and earlier versions), we used to have `RescueSponge` which
6//! consists of a permutation function and an internal state. `RescueSponge`
7//! implements what ark-sponge's `trait CryptographicSponge` (absorb, squeeze
8//! etc.) and `Absorb` is implemented on `RescueParameter` config-marker trait
9//! for finite field types that support rescue permutation.
10//!
11//! When we migrate to `spongefish`'s API design, here are the mapping:
12//! - `Absorb` -> `Unit` (which can be `u8` or `Fp`)
13//! - `CryptographicSponge` -> `DuplexSpongeInterface`
14//! - but we don't manually implement `DuplexSpongeInterface`, instead we
15//! define a new replacement for `RescueSponge` named `RescuePermutation`
16//! which implements `trait Permutation`, and directly use
17//! `DuplexSponge<C:Permutation>` in spongefish
18//!
19//! Thus the old RescueSponge is now replaced by the new RescueSponge (same
20//! name) with the similar duplex sponge APIs, except that by following
21//! spongefish's design, the state and the sponge behavior are not implemented
22//! on the same struct.
23
24use ark_std::fmt::{self, Debug};
25use spongefish::duplex_sponge::{self, DuplexSponge};
26
27use crate::{Permutation, RescueParameter, RescueVector, STATE_SIZE};
28use zeroize::Zeroize;
29
30/// Duplex sponge from [`RescuePermutation`]
31pub type RescueSponge<F: RescueParameter, const R: usize> = DuplexSponge<RescuePermutation<F, R>>;
32
33/// State of rescue sponge, containing necessary permutation instance.
34/// Replacing `RescueSponge`, see module doc.
35#[derive(Clone, Default)]
36pub struct RescuePermutation<F: RescueParameter, const R: usize> {
37 pub(crate) state: RescueVector<F>,
38 pub(crate) perm: Permutation<F>,
39}
40
41impl<F: RescueParameter, const R: usize> duplex_sponge::Permutation for RescuePermutation<F, R> {
42 type U = F;
43 const N: usize = STATE_SIZE;
44 const R: usize = R;
45
46 fn new(iv: [u8; 32]) -> Self {
47 let perm = Permutation::default();
48 let mut state = RescueVector::default();
49 state.vec[R] = F::from_le_bytes_mod_order(&iv);
50 Self { state, perm }
51 }
52
53 fn permute(&mut self) {
54 self.state = self.perm.eval(&self.state);
55 }
56}
57
58impl<F: RescueParameter, const R: usize> AsRef<[F]> for RescuePermutation<F, R> {
59 fn as_ref(&self) -> &[F] {
60 &self.state.vec
61 }
62}
63
64impl<F: RescueParameter, const R: usize> AsMut<[F]> for RescuePermutation<F, R> {
65 fn as_mut(&mut self) -> &mut [F] {
66 &mut self.state.vec
67 }
68}
69
70impl<F: RescueParameter, const R: usize> Zeroize for RescuePermutation<F, R> {
71 fn zeroize(&mut self) {
72 self.state.zeroize();
73 }
74}
75
76impl<F: RescueParameter, const R: usize> Debug for RescuePermutation<F, R> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 self.state.fmt(f)
79 }
80}