1use crate::{
10 sponge::RescueSponge, Permutation, RescueError, RescueParameter, RescueVector, CRHF_RATE,
11};
12use ark_crypto_primitives::sponge::{
13 CryptographicSponge, FieldBasedCryptographicSponge, SpongeExt,
14};
15use ark_std::{borrow::Borrow, marker::PhantomData, string::ToString, vec::Vec};
16use jf_crhf::CRHF;
17use jf_utils::pad_with_zeros;
18
19#[derive(Debug, Clone)]
21pub struct RescueCRHF<F: RescueParameter> {
22 sponge: RescueSponge<F, CRHF_RATE>,
23}
24
25impl<F: RescueParameter> RescueCRHF<F> {
26 pub fn sponge_with_bit_padding(input: &[F], num_outputs: usize) -> Vec<F> {
36 let mut padded = input.to_vec();
37 padded.push(F::one());
38 pad_with_zeros(&mut padded, CRHF_RATE);
39 Self::sponge_no_padding(padded.as_slice(), num_outputs)
40 .expect("Bug in JF Primitives : bad padding of input for FSKS construction")
41 }
42
43 pub fn sponge_with_zero_padding(input: &[F], num_outputs: usize) -> Vec<F> {
49 let mut padded = input.to_vec();
50 pad_with_zeros(&mut padded, CRHF_RATE);
51 Self::sponge_no_padding(padded.as_slice(), num_outputs)
52 .expect("Bug in JF Primitives : bad padding of input for FSKS construction")
53 }
54
55 pub fn sponge_no_padding(input: &[F], num_output: usize) -> Result<Vec<F>, RescueError> {
59 if input.len() % CRHF_RATE != 0 {
60 return Err(RescueError::ParameterError(
61 "Rescue sponge Error : input to sponge hashing function is not multiple of RATE."
62 .to_string(),
63 ));
64 }
65 let mut r = Self {
67 sponge: RescueSponge::from_state(RescueVector::zero(), &Permutation::default()),
68 };
69 r.sponge.absorb(&input);
70
71 Ok(r.sponge.squeeze_native_field_elements(num_output))
73 }
74}
75
76#[derive(Debug, Clone)]
77pub struct FixedLengthRescueCRHF<
80 F: RescueParameter,
81 const INPUT_LEN: usize,
82 const OUTPUT_LEN: usize,
83>(PhantomData<F>);
84
85impl<F: RescueParameter, const INPUT_LEN: usize, const OUTPUT_LEN: usize> CRHF
86 for FixedLengthRescueCRHF<F, INPUT_LEN, OUTPUT_LEN>
87{
88 type Input = [F; INPUT_LEN];
89 type Output = [F; OUTPUT_LEN];
90 type Error = RescueError;
91
92 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
97 let mut output = [F::zero(); OUTPUT_LEN];
98
99 let res = match INPUT_LEN % CRHF_RATE {
100 0 => RescueCRHF::<F>::sponge_no_padding(input.borrow(), OUTPUT_LEN)?,
101 _ => RescueCRHF::<F>::sponge_with_zero_padding(input.borrow(), OUTPUT_LEN),
102 };
103 if res.len() != OUTPUT_LEN {
104 return Err(RescueError::ParameterError(
105 "Unexpected rescue sponge return length".to_string(),
106 ));
107 }
108
109 output.copy_from_slice(&res[..]);
110 Ok(output)
111 }
112}
113
114#[derive(Debug, Clone)]
115pub struct VariableLengthRescueCRHF<F: RescueParameter, const OUTPUT_LEN: usize>(PhantomData<F>);
117
118impl<F: RescueParameter, const OUTPUT_LEN: usize> CRHF for VariableLengthRescueCRHF<F, OUTPUT_LEN> {
119 type Input = Vec<F>;
120 type Output = [F; OUTPUT_LEN];
121 type Error = RescueError;
122
123 fn evaluate<T: Borrow<Self::Input>>(input: T) -> Result<Self::Output, Self::Error> {
129 let mut output = [F::zero(); OUTPUT_LEN];
130 let res = RescueCRHF::<F>::sponge_with_bit_padding(input.borrow(), OUTPUT_LEN);
131 if res.len() != OUTPUT_LEN {
132 return Err(RescueError::ParameterError(
133 "Unexpected rescue sponge return length".to_string(),
134 ));
135 }
136 output.copy_from_slice(&res[..]);
137 Ok(output)
138 }
139}