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}