1use crate::{
2 error,
3 hash::{hash_points, hash_to_curve},
4};
5use k256::{
6 elliptic_curve::{
7 rand_core::OsRng,
8 sec1::{FromEncodedPoint, ToEncodedPoint},
9 subtle::ConditionallyNegatable,
10 Field, PrimeField,
11 },
12 AffinePoint, EncodedPoint, FieldBytes, ProjectivePoint, PublicKey, Scalar, SecretKey,
13};
14use serde::{Deserialize, Serialize};
15use tiny_keccak::{Hasher, Keccak};
16
17#[derive(Clone)]
19#[derive(Debug)]
20#[derive(Eq, PartialEq)]
21#[derive(Serialize, Deserialize)]
22pub struct ECVRFProof {
23 pub gamma: AffinePoint,
25 pub c: Scalar,
27 pub s: Scalar,
29 pub y: Scalar,
31 pub pk: PublicKey,
33}
34
35pub struct ECVRF {
37 secret_key: SecretKey,
38 public_key: PublicKey,
39}
40
41impl ECVRF {
42 pub fn new(secret_key: SecretKey) -> Self {
44 let public_key = PublicKey::from_secret_scalar(&secret_key.to_nonzero_scalar());
45 ECVRF {
46 secret_key,
47 public_key,
48 }
49 }
50
51 pub fn new_from_bytes(secret_key: &[u8]) -> Result<Self, error::Error> {
52 let secret_key =
53 SecretKey::from_slice(secret_key).map_err(|_| error::Error::UnknowError)?;
54 let public_key = PublicKey::from_secret_scalar(&secret_key.to_nonzero_scalar());
55 Ok(ECVRF {
56 secret_key,
57 public_key,
58 })
59 }
60
61 pub fn prove(&self, alpha: &[u8]) -> Result<ECVRFProof, error::Error> {
63 let alpha = Self::generate_alpha(alpha);
64
65 let pub_affine: AffinePoint = self.public_key.into();
66 let secret_key: Scalar = *self.secret_key.to_nonzero_scalar();
67
68 let h = hash_to_curve(&alpha, Some(&pub_affine));
70
71 let gamma = h * secret_key;
73
74 let k = Scalar::random(&mut OsRng);
77
78 let kg = ProjectivePoint::GENERATOR * k;
80
81 let kh = h * k;
83
84 let c = hash_points(
86 &AffinePoint::GENERATOR,
87 &h,
88 &pub_affine,
89 &gamma.to_affine(),
90 &kg.to_affine(),
91 &kh.to_affine(),
92 );
93
94 let mut neg_c = c;
96 neg_c.conditional_negate(1.into());
97 let s = k + neg_c * secret_key;
98
99 let mut output = [0u8; 32];
101 let mut hasher = Keccak::v256();
102 hasher.update(gamma.to_encoded_point(true).as_bytes());
103 hasher.finalize(&mut output);
104 let bytes = FieldBytes::from_slice(&output);
105 let y = Scalar::from_repr(*bytes).unwrap();
106
107 Ok(ECVRFProof {
108 gamma: gamma.to_affine(),
109 c,
110 s,
111 y,
112 pk: self.public_key,
113 })
114 }
115
116 pub fn verify(alpha: &[u8], vrf_proof: &ECVRFProof, public_key: &[u8]) -> bool {
118 let alpha = Self::generate_alpha(alpha);
119 let pub_encoded = EncodedPoint::from_bytes(public_key).unwrap();
120 let pub_point = ProjectivePoint::from_encoded_point(&pub_encoded).unwrap();
121 let u = pub_point * vrf_proof.c + ProjectivePoint::GENERATOR * vrf_proof.s;
122
123 let h = hash_to_curve(&alpha, Some(&pub_point.to_affine()));
124
125 let witness_gamma = ProjectivePoint::from(vrf_proof.gamma) * vrf_proof.c;
127
128 let witness_hash = ProjectivePoint::from(h) * vrf_proof.s;
130
131 let v = witness_gamma + witness_hash;
133
134 let computed_c = hash_points(
136 &AffinePoint::GENERATOR,
137 &h,
138 &pub_point.to_affine(),
139 &vrf_proof.gamma,
140 &u.to_affine(),
141 &v.to_affine(),
142 );
143
144 let mut output = [0u8; 32];
146 let mut hasher = Keccak::v256();
147 hasher.update(vrf_proof.gamma.to_encoded_point(true).as_bytes());
148 hasher.finalize(&mut output);
149
150 let bytes = FieldBytes::from_slice(&output);
151 let computed_y = Scalar::from_repr(*bytes).unwrap();
152
153 computed_c == vrf_proof.c && computed_y == vrf_proof.y
154 }
155
156 fn generate_alpha(alpha: &[u8]) -> Scalar {
157 let mut output = [0u8; 32];
158 let mut hasher = Keccak::v256();
159 hasher.update(alpha);
160 hasher.finalize(&mut output);
161
162 let bytes = FieldBytes::from_slice(&output);
163 Scalar::from_repr(*bytes).unwrap()
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use k256::{
170 elliptic_curve::{rand_core::OsRng, sec1::ToEncodedPoint},
171 PublicKey, SecretKey,
172 };
173
174 use crate::ECVRF;
175
176 const TEST_ALPHA: &[u8] = b"test alphaddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
177
178 #[test]
179 fn success_proof_and_verify() {
180 let secret_key = SecretKey::random(&mut OsRng);
181 let public_key = PublicKey::from_secret_scalar(&secret_key.to_nonzero_scalar());
182
183 let ecvrf = ECVRF::new(secret_key);
184 let proof = ecvrf.prove(TEST_ALPHA).unwrap();
185 assert_eq!(proof.pk, public_key);
186
187 let result = ECVRF::verify(
188 TEST_ALPHA,
189 &proof,
190 public_key.to_encoded_point(true).as_bytes(),
191 );
192 assert!(result);
193 }
194}