1use crate::{
10 sponge::RescueSponge, Permutation, RescueError, RescueParameter, RescueVector, STATE_SIZE,
11};
12use ark_crypto_primitives::sponge::{
13 CryptographicSponge, FieldBasedCryptographicSponge, SpongeExt,
14};
15use ark_std::{borrow::Borrow, marker::PhantomData, string::ToString, vec::Vec};
16use jf_prf::PRF;
17use jf_utils::pad_with_zeros;
18
19#[derive(Debug, Clone)]
21pub(crate) struct RescuePRFCore<F: RescueParameter> {
22 sponge: RescueSponge<F, STATE_SIZE>,
23}
24
25impl<F: RescueParameter> RescuePRFCore<F> {
26 pub(crate) fn full_state_keyed_sponge_with_zero_padding(
30 key: &F,
31 input: &[F],
32 num_outputs: usize,
33 ) -> Result<Vec<F>, RescueError> {
34 let mut padded = input.to_vec();
35 pad_with_zeros(&mut padded, STATE_SIZE);
36 Self::full_state_keyed_sponge_no_padding(key, padded.as_slice(), num_outputs)
37 }
38
39 pub(crate) fn full_state_keyed_sponge_no_padding(
43 key: &F,
44 input: &[F],
45 num_outputs: usize,
46 ) -> Result<Vec<F>, RescueError> {
47 if input.len() % STATE_SIZE != 0 {
48 return Err(RescueError::ParameterError(
49 "Rescue FSKS PRF Error: input to prf function is not multiple of STATE_SIZE."
50 .to_string(),
51 ));
52 }
53 let mut state = RescueVector::zero();
55 state.vec[STATE_SIZE - 1] = *key;
56 let mut r = Self {
57 sponge: RescueSponge::from_state(state, &Permutation::default()),
58 };
59 r.sponge.absorb(&input);
60
61 Ok(r.sponge.squeeze_native_field_elements(num_outputs))
63 }
64}
65
66#[derive(Debug, Clone)]
67pub struct RescuePRF<F: RescueParameter, const INPUT_LEN: usize, const OUTPUT_LEN: usize>(
70 PhantomData<F>,
71);
72
73impl<F: RescueParameter, const INPUT_LEN: usize, const OUTPUT_LEN: usize> PRF
74 for RescuePRF<F, INPUT_LEN, OUTPUT_LEN>
75{
76 type Input = [F; INPUT_LEN];
77 type Output = [F; OUTPUT_LEN];
78 type Seed = F;
79 type Error = RescueError;
80
81 fn evaluate<S: Borrow<Self::Seed>, I: Borrow<Self::Input>>(
82 seed: S,
83 input: I,
84 ) -> Result<Self::Output, Self::Error> {
85 let mut output = [F::zero(); OUTPUT_LEN];
86 output.clone_from_slice(&RescuePRFCore::full_state_keyed_sponge_with_zero_padding(
87 seed.borrow(),
88 input.borrow(),
89 OUTPUT_LEN,
90 )?);
91 Ok(output)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use crate::{
98 crhf::RescueCRHF,
99 prf::{RescuePRF, RescuePRFCore, PRF},
100 RescueParameter,
101 };
102 use ark_bls12_377::{Fq as Fq377, Fr as Fr377};
103 use ark_bls12_381::Fr as Fr381;
104 use ark_bn254::{Fq as Fq254, Fr as Fr254};
105 use ark_ed_on_bls12_377::Fq as FqEd377;
106 use ark_ed_on_bls12_381::Fq as FqEd381;
107 use ark_ed_on_bn254::Fq as FqEd254;
108 use ark_std::{vec, UniformRand};
109 macro_rules! test_prf {
110 ($tr:tt) => {
111 let mut rng = jf_utils::test_rng();
112 let seed = $tr::rand(&mut rng);
113 let input = [$tr::from(1u8)];
114
115 assert!(RescuePRF::<$tr, 1, 15>::evaluate(&seed, &input).is_ok());
116 assert_eq!(
118 RescuePRF::<$tr, 1, 15>::evaluate(&seed, &input)
119 .unwrap()
120 .to_vec(),
121 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&seed, &input, 15)
122 .unwrap()
123 );
124 };
125 }
126
127 #[test]
128 pub fn test_prf() {
129 test_prf!(FqEd254);
130 test_prf!(FqEd377);
131 test_prf!(FqEd381);
132 test_prf!(Fq377);
133 test_prf!(Fq254);
134 }
135
136 #[test]
137 fn test_fsks_no_padding_errors() {
138 test_fsks_no_padding_errors_helper::<Fq254>();
139 test_fsks_no_padding_errors_helper::<Fr254>();
140 test_fsks_no_padding_errors_helper::<Fr377>();
141 test_fsks_no_padding_errors_helper::<Fr381>();
142 test_fsks_no_padding_errors_helper::<Fq377>();
143 }
144 fn test_fsks_no_padding_errors_helper<F: RescueParameter>() {
145 let key = F::rand(&mut jf_utils::test_rng());
146 let input = vec![F::from(9u64); 4];
147 assert!(
148 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, input.as_slice(), 1).is_ok()
149 );
150 let input = vec![F::from(9u64); 12];
151 assert!(
152 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, input.as_slice(), 1).is_ok()
153 );
154
155 let input = vec![F::from(9u64); 10];
157 assert!(
158 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, input.as_slice(), 1).is_err()
159 );
160 let input = vec![F::from(9u64)];
161 assert!(
162 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, input.as_slice(), 1).is_err()
163 );
164
165 let input = vec![];
166 assert!(
167 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, input.as_slice(), 1).is_ok()
168 );
169 }
170
171 #[test]
172 fn test_variable_output_sponge_and_fsks() {
173 test_variable_output_sponge_and_fsks_helper::<Fq254>();
174 test_variable_output_sponge_and_fsks_helper::<Fr254>();
175 test_variable_output_sponge_and_fsks_helper::<Fr377>();
176 test_variable_output_sponge_and_fsks_helper::<Fr381>();
177 test_variable_output_sponge_and_fsks_helper::<Fq377>();
178 }
179 fn test_variable_output_sponge_and_fsks_helper<F: RescueParameter>() {
180 let input = [F::zero(), F::one(), F::zero()];
181 assert_eq!(RescueCRHF::sponge_with_bit_padding(&input, 0).len(), 0);
182 assert_eq!(RescueCRHF::sponge_with_bit_padding(&input, 1).len(), 1);
183 assert_eq!(RescueCRHF::sponge_with_bit_padding(&input, 2).len(), 2);
184 assert_eq!(RescueCRHF::sponge_with_bit_padding(&input, 3).len(), 3);
185 assert_eq!(RescueCRHF::sponge_with_bit_padding(&input, 10).len(), 10);
186
187 assert_eq!(RescueCRHF::sponge_no_padding(&input, 0).unwrap().len(), 0);
188 assert_eq!(RescueCRHF::sponge_no_padding(&input, 1).unwrap().len(), 1);
189 assert_eq!(RescueCRHF::sponge_no_padding(&input, 2).unwrap().len(), 2);
190 assert_eq!(RescueCRHF::sponge_no_padding(&input, 3).unwrap().len(), 3);
191 assert_eq!(RescueCRHF::sponge_no_padding(&input, 10).unwrap().len(), 10);
192
193 let key = F::rand(&mut jf_utils::test_rng());
194 let input = [F::zero(), F::one(), F::zero(), F::zero()];
195 assert_eq!(
196 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&key, &input, 0)
197 .unwrap()
198 .len(),
199 0
200 );
201 assert_eq!(
202 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&key, &input, 1)
203 .unwrap()
204 .len(),
205 1
206 );
207 assert_eq!(
208 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&key, &input, 2)
209 .unwrap()
210 .len(),
211 2
212 );
213 assert_eq!(
214 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&key, &input, 4)
215 .unwrap()
216 .len(),
217 4
218 );
219 assert_eq!(
220 RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&key, &input, 10)
221 .unwrap()
222 .len(),
223 10
224 );
225 assert_eq!(
226 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, &input, 0)
227 .unwrap()
228 .len(),
229 0
230 );
231 assert_eq!(
232 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, &input, 1)
233 .unwrap()
234 .len(),
235 1
236 );
237 assert_eq!(
238 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, &input, 2)
239 .unwrap()
240 .len(),
241 2
242 );
243 assert_eq!(
244 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, &input, 4)
245 .unwrap()
246 .len(),
247 4
248 );
249 assert_eq!(
250 RescuePRFCore::full_state_keyed_sponge_no_padding(&key, &input, 10)
251 .unwrap()
252 .len(),
253 10
254 );
255 }
256}