1use super::*;
28
29pub trait IetfSuite: Suite {}
30
31impl<T> IetfSuite for T where T: Suite {}
32
33#[derive(Debug, Clone)]
39pub struct Proof<S: IetfSuite> {
40 pub c: ScalarField<S>,
41 pub s: ScalarField<S>,
42}
43
44impl<S: IetfSuite> CanonicalSerialize for Proof<S> {
45 fn serialize_with_mode<W: ark_serialize::Write>(
46 &self,
47 mut writer: W,
48 compress: ark_serialize::Compress,
49 ) -> Result<(), ark_serialize::SerializationError> {
50 let c_buf = codec::scalar_encode::<S>(&self.c);
51 if c_buf.len() < S::CHALLENGE_LEN {
52 return Err(ark_serialize::SerializationError::NotEnoughSpace);
54 }
55 let buf = if S::Codec::BIG_ENDIAN {
56 &c_buf[c_buf.len() - S::CHALLENGE_LEN..]
57 } else {
58 &c_buf[..S::CHALLENGE_LEN]
59 };
60 writer.write_all(buf)?;
61 self.s.serialize_with_mode(&mut writer, compress)?;
62 Ok(())
63 }
64
65 fn serialized_size(&self, _compress_always: ark_serialize::Compress) -> usize {
66 S::CHALLENGE_LEN + self.s.compressed_size()
67 }
68}
69
70impl<S: IetfSuite> CanonicalDeserialize for Proof<S> {
71 fn deserialize_with_mode<R: ark_serialize::Read>(
72 mut reader: R,
73 compress: ark_serialize::Compress,
74 validate: ark_serialize::Validate,
75 ) -> Result<Self, ark_serialize::SerializationError> {
76 let mut c_buf = ark_std::vec![0; S::CHALLENGE_LEN];
77 if reader.read_exact(&mut c_buf[..]).is_err() {
78 return Err(ark_serialize::SerializationError::InvalidData);
79 }
80 let c = S::Codec::scalar_decode(&c_buf);
81 let s = <ScalarField<S> as CanonicalDeserialize>::deserialize_with_mode(
82 &mut reader,
83 compress,
84 validate,
85 )?;
86 Ok(Proof { c, s })
87 }
88}
89
90impl<S: IetfSuite> ark_serialize::Valid for Proof<S> {
91 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
92 self.c.check()?;
93 self.s.check()?;
94 Ok(())
95 }
96}
97
98pub trait Prover<S: IetfSuite> {
103 fn prove(&self, input: Input<S>, output: Output<S>, ad: impl AsRef<[u8]>) -> Proof<S>;
112}
113
114pub trait Verifier<S: IetfSuite> {
119 fn verify(
131 &self,
132 input: Input<S>,
133 output: Output<S>,
134 aux: impl AsRef<[u8]>,
135 proof: &Proof<S>,
136 ) -> Result<(), Error>;
137}
138
139impl<S: IetfSuite> Prover<S> for Secret<S> {
140 fn prove(&self, input: Input<S>, output: Output<S>, ad: impl AsRef<[u8]>) -> Proof<S> {
151 let k = S::nonce(&self.scalar, input);
152
153 let k_b = smul!(S::generator(), k).into_affine();
154 let k_h = smul!(input.0, k).into_affine();
155
156 let c = S::challenge(
157 &[&self.public.0, &input.0, &output.0, &k_b, &k_h],
158 ad.as_ref(),
159 );
160 let s = k + c * self.scalar;
161 Proof { c, s }
162 }
163}
164
165impl<S: IetfSuite> Verifier<S> for Public<S> {
166 fn verify(
177 &self,
178 input: Input<S>,
179 output: Output<S>,
180 aux: impl AsRef<[u8]>,
181 proof: &Proof<S>,
182 ) -> Result<(), Error> {
183 let Proof { c, s } = proof;
184
185 let s_b = S::generator() * s;
186 let c_y = self.0 * c;
187 let u = (s_b - c_y).into_affine();
188
189 let s_h = input.0 * s;
190 let c_o = output.0 * c;
191 let v = (s_h - c_o).into_affine();
192
193 let c_exp = S::challenge(&[&self.0, &input.0, &output.0, &u, &v], aux.as_ref());
194 (&c_exp == c)
195 .then_some(())
196 .ok_or(Error::VerificationFailure)
197 }
198}
199
200#[cfg(test)]
201pub mod testing {
202 use super::*;
203 use crate::testing::{self as common, SuiteExt};
204
205 pub fn prove_verify<S: IetfSuite>() {
206 use ietf::{Prover, Verifier};
207
208 let secret = Secret::<S>::from_seed(common::TEST_SEED);
209 let public = secret.public();
210 let input = Input::from(common::random_val(None));
211 let output = secret.output(input);
212
213 let proof = secret.prove(input, output, b"foo");
214 let result = public.verify(input, output, b"foo", &proof);
215 assert!(result.is_ok());
216 }
217
218 #[macro_export]
219 macro_rules! ietf_suite_tests {
220 ($suite:ty) => {
221 mod ietf {
222 use super::*;
223
224 #[test]
225 fn prove_verify() {
226 $crate::ietf::testing::prove_verify::<$suite>();
227 }
228
229 $crate::test_vectors!($crate::ietf::testing::TestVector<$suite>);
230 }
231 };
232 }
233
234 pub struct TestVector<S: IetfSuite> {
235 pub base: common::TestVector<S>,
236 pub c: ScalarField<S>,
237 pub s: ScalarField<S>,
238 }
239
240 impl<S: IetfSuite> core::fmt::Debug for TestVector<S> {
241 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
242 let c = hex::encode(codec::scalar_encode::<S>(&self.c));
243 let s = hex::encode(codec::scalar_encode::<S>(&self.s));
244 f.debug_struct("TestVector")
245 .field("base", &self.base)
246 .field("proof_c", &c)
247 .field("proof_s", &s)
248 .finish()
249 }
250 }
251
252 impl<S> common::TestVectorTrait for TestVector<S>
253 where
254 S: IetfSuite + SuiteExt + std::fmt::Debug,
255 {
256 fn name() -> String {
257 S::suite_name() + "_ietf"
258 }
259
260 fn new(comment: &str, seed: &[u8], alpha: &[u8], salt: &[u8], ad: &[u8]) -> Self {
261 use super::Prover;
262 let base = common::TestVector::new(comment, seed, alpha, salt, ad);
263 let input = Input::from(base.h);
265 let output = Output::from(base.gamma);
266 let sk = Secret::from_scalar(base.sk);
267 let proof: Proof<S> = sk.prove(input, output, ad);
268 Self {
269 base,
270 c: proof.c,
271 s: proof.s,
272 }
273 }
274
275 fn from_map(map: &common::TestVectorMap) -> Self {
276 let base = common::TestVector::from_map(map);
277 let c = S::Codec::scalar_decode(&map.get_bytes("proof_c"));
278 let s = S::Codec::scalar_decode(&map.get_bytes("proof_s"));
279 Self { base, c, s }
280 }
281
282 fn to_map(&self) -> common::TestVectorMap {
283 let buf = codec::scalar_encode::<S>(&self.c);
284 let proof_c = if S::Codec::BIG_ENDIAN {
285 let len = buf.len();
286 &buf[len - S::CHALLENGE_LEN..]
287 } else {
288 &buf[..S::CHALLENGE_LEN]
289 };
290 let items = [
291 ("proof_c", hex::encode(proof_c)),
292 ("proof_s", hex::encode(codec::scalar_encode::<S>(&self.s))),
293 ];
294 let mut map = self.base.to_map();
295 items.into_iter().for_each(|(name, value)| {
296 map.0.insert(name.to_string(), value);
297 });
298 map
299 }
300
301 fn run(&self) {
302 self.base.run();
303 let input = Input::<S>::from(self.base.h);
304 let output = Output::from(self.base.gamma);
305 let sk = Secret::from_scalar(self.base.sk);
306 let proof = sk.prove(input, output, &self.base.ad);
307 assert_eq!(self.c, proof.c, "VRF proof challenge ('c') mismatch");
308 assert_eq!(self.s, proof.s, "VRF proof response ('s') mismatch");
309
310 let pk = Public(self.base.pk);
311 assert!(pk.verify(input, output, &self.base.ad, &proof).is_ok());
312 }
313 }
314}