darkfi_sdk/crypto/
ecvrf.rs1#![allow(non_snake_case)]
21
22#[cfg(feature = "async")]
23use darkfi_serial::async_trait;
24use darkfi_serial::{SerialDecodable, SerialEncodable};
25use halo2_gadgets::ecc::chip::FixedPoint;
26use pasta_curves::{
27 arithmetic::CurveExt,
28 group::{
29 ff::{FromUniformBytes, PrimeField},
30 GroupEncoding,
31 },
32 pallas,
33};
34
35use super::{
36 constants::NullifierK,
37 util::{fp_mod_fv, hash_to_scalar},
38 PublicKey, SecretKey,
39};
40
41const VRF_DOMAIN: &str = "DarkFi_ECVRF";
43
44#[derive(Copy, Clone, Debug, SerialEncodable, SerialDecodable)]
46pub struct VrfProof {
47 gamma: pallas::Point,
48 c: blake3::Hash,
49 s: pallas::Scalar,
50}
51
52impl VrfProof {
53 pub fn prove(x: SecretKey, alpha_string: &[u8]) -> Self {
56 let Y = PublicKey::from_secret(x);
57
58 let mut message = vec![];
59 message.extend_from_slice(&Y.to_bytes());
60 message.extend_from_slice(alpha_string);
61 let H = pallas::Point::hash_to_curve(VRF_DOMAIN)(&message);
62
63 let gamma = H * fp_mod_fv(x.inner());
64
65 let k = hash_to_scalar(VRF_DOMAIN.as_bytes(), &[&x.inner().to_repr(), &H.to_bytes()]);
67
68 let mut hasher = blake3::Hasher::new();
69 hasher.update(&H.to_bytes());
70 hasher.update(&gamma.to_bytes());
71 hasher.update(&(NullifierK.generator() * k).to_bytes());
74 hasher.update(&(H * k).to_bytes());
75 let c = hasher.finalize();
76
77 let mut c_scalar = [0u8; 64];
78 c_scalar[..blake3::OUT_LEN].copy_from_slice(c.as_bytes());
79 let c_scalar = pallas::Scalar::from_uniform_bytes(&c_scalar);
80
81 let s = k + c_scalar * fp_mod_fv(x.inner());
82
83 Self { gamma, c, s }
84 }
85
86 pub fn verify(&self, Y: PublicKey, alpha_string: &[u8]) -> bool {
88 let mut message = vec![];
89 message.extend_from_slice(&Y.to_bytes());
90 message.extend_from_slice(alpha_string);
91 let H = pallas::Point::hash_to_curve(VRF_DOMAIN)(&message);
92
93 let mut c = [0u8; 64];
94 c[..blake3::OUT_LEN].copy_from_slice(self.c.as_bytes());
95 let c_scalar = pallas::Scalar::from_uniform_bytes(&c);
96
97 let U = NullifierK.generator() * self.s - Y.inner() * c_scalar;
98 let V = H * self.s - self.gamma * c_scalar;
99
100 let mut hasher = blake3::Hasher::new();
101 hasher.update(&H.to_bytes());
102 hasher.update(&self.gamma.to_bytes());
103 hasher.update(&U.to_bytes());
104 hasher.update(&V.to_bytes());
105
106 hasher.finalize() == self.c
107 }
108
109 pub fn hash_output(&self) -> blake3::Hash {
113 let mut hasher = blake3::Hasher::new();
114 hasher.update(VRF_DOMAIN.as_bytes());
115 hasher.update(&[0x03]);
116 hasher.update(&self.gamma.to_bytes());
117 hasher.finalize()
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use rand::rngs::OsRng;
125
126 #[test]
127 fn ecvrf() {
128 let secret_key = SecretKey::random(&mut OsRng);
130 let public_key = PublicKey::from_secret(secret_key);
132 let input = [0xde, 0xad, 0xbe, 0xef];
134
135 let proof = VrfProof::prove(secret_key, &input);
136 assert!(proof.verify(public_key, &input));
137
138 let forged_public_key = PublicKey::from_secret(SecretKey::random(&mut OsRng));
140 assert!(!proof.verify(forged_public_key, &input));
141
142 let forged_input = [0xde, 0xad, 0xba, 0xbe];
144 assert!(!proof.verify(public_key, &forged_input));
145 }
146}