1use super::Vrf;
9use ark_std::{
10 boxed::Box,
11 rand::{CryptoRng, RngCore},
12 string::{String, ToString},
13 vec::Vec,
14};
15use digest::{Digest, DynDigest};
16use displaydoc::Display;
17use jf_signature::{
18 bls_over_bls12381::{BLSSignKey, BLSSignature, BLSSignatureScheme, BLSVerKey},
19 SignatureScheme,
20};
21use sha2::{Sha256, Sha512};
22
23#[allow(non_camel_case_types)]
25#[derive(Debug)]
26pub enum BLSVRFCipherSuite {
27 VRF_BLS_12_381_SHA256,
29 VRF_BLS_12_381_SHA512,
31}
32
33pub struct BLSVRFScheme {
36 hasher: Box<dyn DynDigest>,
37}
38
39impl BLSVRFScheme {
40 pub fn new(cs_id: BLSVRFCipherSuite) -> Self {
42 match cs_id {
43 BLSVRFCipherSuite::VRF_BLS_12_381_SHA256 => Self {
44 hasher: Box::new(Sha256::new()),
45 },
46 BLSVRFCipherSuite::VRF_BLS_12_381_SHA512 => Self {
47 hasher: Box::new(Sha512::new()),
48 },
49 }
50 }
51}
52
53#[derive(Debug, Display)]
55pub struct BLSVRFError(String);
56impl ark_std::error::Error for BLSVRFError {}
57
58impl Vrf for BLSVRFScheme {
59 type PublicParameter = ();
64
65 type PublicKey = BLSVerKey;
67
68 type SecretKey = BLSSignKey;
70
71 type Proof = BLSSignature;
73
74 type Input = Vec<u8>;
76
77 type Output = Vec<u8>;
79
80 type Error = BLSVRFError;
82
83 fn param_gen<R: CryptoRng + RngCore>(
85 &self,
86 _prng: Option<&mut R>,
87 ) -> Result<Self::PublicParameter, BLSVRFError> {
88 Ok(())
89 }
90
91 fn key_gen<R: CryptoRng + RngCore>(
93 &self,
94 pp: &Self::PublicParameter,
95 prng: &mut R,
96 ) -> Result<(Self::SecretKey, Self::PublicKey), BLSVRFError> {
97 <BLSSignatureScheme as SignatureScheme>::key_gen(pp, prng)
98 .map_err(|e| BLSVRFError(e.to_string()))
99 }
100
101 fn prove<R: CryptoRng + RngCore>(
103 &self,
104 pp: &Self::PublicParameter,
105 secret_key: &Self::SecretKey,
106 input: &Self::Input,
107 prng: &mut R,
108 ) -> Result<Self::Proof, BLSVRFError> {
109 <BLSSignatureScheme as SignatureScheme>::sign(pp, secret_key, input, prng)
110 .map_err(|e| BLSVRFError(e.to_string()))
111 }
112
113 fn proof_to_hash(
115 &mut self,
116 _pp: &Self::PublicParameter,
117 proof: &Self::Proof,
118 ) -> Result<Self::Output, BLSVRFError> {
119 let proof_serialized = proof.serialize();
120 let mut hasher = (*self.hasher).box_clone();
121 hasher.update(&proof_serialized);
122 let output = hasher.finalize();
123 Ok(output.to_vec())
124 }
125
126 fn verify(
128 &mut self,
129 pp: &Self::PublicParameter,
130 proof: &Self::Proof,
131 public_key: &Self::PublicKey,
132 input: &Self::Input,
133 ) -> Result<(bool, Option<Self::Output>), BLSVRFError> {
134 if <BLSSignatureScheme as SignatureScheme>::verify(pp, public_key, input, proof).is_ok() {
135 Ok((true, Some(Self::proof_to_hash(self, pp, proof).unwrap())))
136 } else {
137 Ok((false, None))
138 }
139 }
140}
141
142#[cfg(test)]
143mod test {
144 use super::*;
145 use ark_std::rand::Rng;
146 use jf_utils::test_rng;
147
148 pub(crate) fn sign_and_verify<H: Digest>(
149 vrf: &mut BLSVRFScheme,
150 message: &<BLSVRFScheme as Vrf>::Input,
151 bad_message: &<BLSVRFScheme as Vrf>::Input,
152 ) {
153 let rng = &mut test_rng();
154
155 let (sk, pk) = vrf.key_gen(&(), rng).unwrap();
156 let vrf_proof = vrf.prove(&(), &sk, message, rng).unwrap();
157 let vrf_output = vrf.proof_to_hash(&(), &vrf_proof).unwrap();
158 let (is_correct, output) = vrf.verify(&(), &vrf_proof, &pk, message).unwrap();
159 assert!(is_correct);
160 assert!(output.is_some());
162
163 let out = vrf.evaluate(&(), &sk, message, rng).unwrap();
165 assert_eq!(out, vrf_output);
166
167 let mut hasher = H::new();
169 hasher.update(vrf_proof.serialize());
170 let direct_hash_output = hasher.finalize().to_vec();
171 assert_eq!(direct_hash_output, vrf_output);
172
173 let (is_correct, _) = vrf.verify(&(), &vrf_proof, &pk, bad_message).unwrap();
176 assert!(!is_correct);
177 }
178
179 #[test]
180 fn test_bls_vrf() {
181 let rng = &mut test_rng();
182 for _ in 0..10 {
183 let message = rng.gen::<[u8; 32]>().to_vec();
184 let message_bad = message.clone()[..31].to_vec();
186 let mut blsvrf256 = BLSVRFScheme::new(BLSVRFCipherSuite::VRF_BLS_12_381_SHA256);
187
188 sign_and_verify::<Sha256>(&mut blsvrf256, &message, &message_bad);
189
190 let mut blsvrf512 = BLSVRFScheme::new(BLSVRFCipherSuite::VRF_BLS_12_381_SHA512);
191 sign_and_verify::<Sha512>(&mut blsvrf512, &message, &message_bad);
192 }
193 }
194}