1use crate::{
2 CryptoMaterialError, HashValue, PrivateKey, PublicKey, Uniform,
3 VRFPrivateKey, VRFProof, VRFPublicKey, ValidCryptoMaterial,
4 ValidCryptoMaterialStringExt,
5};
6use anyhow::{anyhow, Result};
7use diem_crypto_derive::{
8 DeserializeKey, SerializeKey, SilentDebug, SilentDisplay,
9};
10use lazy_static::lazy_static;
11use openssl::{ec, nid::Nid};
12use parking_lot::Mutex;
13use std::{
14 convert::TryFrom,
15 fmt::{self, Formatter},
16};
17use vrf::{
18 openssl::{CipherSuite, ECVRF},
19 VRF,
20};
21
22lazy_static! {
24 pub static ref VRF_CONTEXT: Mutex<ECVRF> = Mutex::new(
26 ECVRF::from_suite(CipherSuite::SECP256K1_SHA256_TAI)
27 .expect("VRF context initialization error")
28 );
29}
30
31#[derive(
33 DeserializeKey,
34 Clone,
35 SerializeKey,
36 SilentDebug,
37 SilentDisplay,
38 Eq,
39 PartialEq,
40)]
41pub struct EcVrfPrivateKey(Vec<u8>);
42
43#[derive(DeserializeKey, Clone, SerializeKey, Debug)]
45pub struct EcVrfPublicKey(Vec<u8>);
46
47#[derive(DeserializeKey, Clone, SerializeKey, Debug)]
49pub struct EcVrfProof(Vec<u8>);
50
51impl VRFPrivateKey for EcVrfPrivateKey {
52 type ProofMaterial = EcVrfProof;
53 type PublicKeyMaterial = EcVrfPublicKey;
54
55 fn compute(&self, seed: &[u8]) -> Result<Self::ProofMaterial> {
56 match VRF_CONTEXT.lock().prove(&self.0, seed) {
57 Ok(proof) => Ok(EcVrfProof(proof)),
58 Err(e) => Err(anyhow!(e)),
59 }
60 }
61}
62
63impl VRFPublicKey for EcVrfPublicKey {
64 type PrivateKeyMaterial = EcVrfPrivateKey;
65 type ProofMaterial = EcVrfProof;
66}
67
68impl VRFProof for EcVrfProof {
69 type PrivateKeyMaterial = EcVrfPrivateKey;
70 type PublicKeyMaterial = EcVrfPublicKey;
71
72 fn to_hash(&self) -> Result<HashValue> {
73 match VRF_CONTEXT.lock().proof_to_hash(&self.0) {
74 Ok(h) => HashValue::from_slice(&h).map_err(|e| anyhow!(e)),
75 Err(e) => Err(anyhow!(e)),
76 }
77 }
78
79 fn verify(
80 &self, seed: &[u8], public_key: &Self::PublicKeyMaterial,
81 ) -> Result<HashValue> {
82 match VRF_CONTEXT.lock().verify(&public_key.0, &self.0, seed) {
83 Ok(h) => HashValue::from_slice(&h).map_err(|e| anyhow!(e)),
84 Err(e) => Err(anyhow!(e)),
85 }
86 }
87}
88
89impl PrivateKey for EcVrfPrivateKey {
90 type PublicKeyMaterial = EcVrfPublicKey;
91}
92
93impl PublicKey for EcVrfPublicKey {
94 type PrivateKeyMaterial = EcVrfPrivateKey;
95}
96
97impl fmt::Display for EcVrfPublicKey {
98 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99 write!(f, "{}", self.to_encoded_string().map_err(|_| fmt::Error)?)
100 }
101}
102
103impl From<Vec<u8>> for EcVrfPublicKey {
104 fn from(raw: Vec<u8>) -> Self { EcVrfPublicKey(raw) }
105}
106
107impl From<&EcVrfPrivateKey> for EcVrfPublicKey {
108 fn from(private_key: &EcVrfPrivateKey) -> Self {
109 EcVrfPublicKey(
110 VRF_CONTEXT
111 .lock()
112 .derive_public_key(&private_key.0)
113 .expect("VRF derive public key error"),
114 )
115 }
116}
117
118impl TryFrom<&[u8]> for EcVrfPrivateKey {
119 type Error = CryptoMaterialError;
120
121 fn try_from(
124 bytes: &[u8],
125 ) -> std::result::Result<EcVrfPrivateKey, CryptoMaterialError> {
126 Ok(EcVrfPrivateKey(bytes.to_vec()))
128 }
129}
130
131impl TryFrom<&[u8]> for EcVrfPublicKey {
132 type Error = CryptoMaterialError;
133
134 fn try_from(
137 bytes: &[u8],
138 ) -> std::result::Result<EcVrfPublicKey, CryptoMaterialError> {
139 Ok(EcVrfPublicKey(bytes.to_vec()))
141 }
142}
143
144impl TryFrom<&[u8]> for EcVrfProof {
145 type Error = CryptoMaterialError;
146
147 fn try_from(
150 bytes: &[u8],
151 ) -> std::result::Result<EcVrfProof, CryptoMaterialError> {
152 Ok(EcVrfProof(bytes.to_vec()))
154 }
155}
156
157impl std::hash::Hash for EcVrfPublicKey {
158 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
159 let encoded_pubkey = self.to_bytes();
160 state.write(&encoded_pubkey);
161 }
162}
163
164impl PartialEq for EcVrfPublicKey {
165 fn eq(&self, other: &EcVrfPublicKey) -> bool {
166 self.to_bytes() == other.to_bytes()
167 }
168}
169
170impl std::hash::Hash for EcVrfProof {
171 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
172 let encoded_pubkey = ValidCryptoMaterial::to_bytes(self);
173 state.write(&encoded_pubkey);
174 }
175}
176
177impl PartialEq for EcVrfProof {
178 fn eq(&self, other: &EcVrfProof) -> bool {
179 self.to_bytes() == other.to_bytes()
180 }
181}
182
183impl fmt::Display for EcVrfProof {
184 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
185 write!(f, "{}", self.to_encoded_string().map_err(|_| fmt::Error)?)
186 }
187}
188
189impl Eq for EcVrfPublicKey {}
190
191impl Eq for EcVrfProof {}
192
193impl ValidCryptoMaterial for EcVrfPrivateKey {
194 fn to_bytes(&self) -> Vec<u8> { self.0.clone() }
195}
196
197impl ValidCryptoMaterial for EcVrfPublicKey {
198 fn to_bytes(&self) -> Vec<u8> { self.0.clone() }
199}
200
201impl ValidCryptoMaterial for EcVrfProof {
202 fn to_bytes(&self) -> Vec<u8> { self.0.clone() }
203}
204
205impl Uniform for EcVrfPrivateKey {
208 fn generate<R>(_rng: &mut R) -> Self
209 where R: ::rand::RngCore + ::rand::CryptoRng {
210 let ec_group = ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
211 Self(
212 ec::EcKey::generate(&ec_group)
213 .unwrap()
214 .private_key()
215 .to_vec(),
216 )
217 }
218}
219
220#[cfg(any(test, feature = "fuzzing"))]
221use crate::test_utils::{self, KeyPair};
222
223#[cfg(any(test, feature = "fuzzing"))]
225pub fn keypair_strategy(
226) -> impl Strategy<Value = KeyPair<EcVrfPrivateKey, EcVrfPublicKey>> {
227 test_utils::uniform_keypair_strategy::<EcVrfPrivateKey, EcVrfPublicKey>()
228}
229
230#[cfg(any(test, feature = "fuzzing"))]
231use proptest::prelude::*;
232
233#[cfg(any(test, feature = "fuzzing"))]
234impl proptest::arbitrary::Arbitrary for EcVrfPublicKey {
235 type Parameters = ();
236 type Strategy = BoxedStrategy<Self>;
237
238 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
239 crate::test_utils::uniform_keypair_strategy::<
240 EcVrfPrivateKey,
241 EcVrfPublicKey,
242 >()
243 .prop_map(|v| v.public_key)
244 .boxed()
245 }
246}