diem_crypto/
ec_vrf.rs

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
22// TODO(lpl): Choose a curve;
23lazy_static! {
24    /// VRF Cipher context. Mutex is needed because functions require `&mut self`.
25    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/// Elliptic Curve VRF private key
32#[derive(
33    DeserializeKey,
34    Clone,
35    SerializeKey,
36    SilentDebug,
37    SilentDisplay,
38    Eq,
39    PartialEq,
40)]
41pub struct EcVrfPrivateKey(Vec<u8>);
42
43/// Elliptic Curve VRF public key
44#[derive(DeserializeKey, Clone, SerializeKey, Debug)]
45pub struct EcVrfPublicKey(Vec<u8>);
46
47/// Elliptic Curve VRF proof
48#[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    /// Deserialize an EcVrfPrivateKey. This method will also check for key
122    /// validity.
123    fn try_from(
124        bytes: &[u8],
125    ) -> std::result::Result<EcVrfPrivateKey, CryptoMaterialError> {
126        // TODO(lpl): Check validation.
127        Ok(EcVrfPrivateKey(bytes.to_vec()))
128    }
129}
130
131impl TryFrom<&[u8]> for EcVrfPublicKey {
132    type Error = CryptoMaterialError;
133
134    /// Deserialize an EcVrfPrivateKey. This method will also check for key
135    /// validity.
136    fn try_from(
137        bytes: &[u8],
138    ) -> std::result::Result<EcVrfPublicKey, CryptoMaterialError> {
139        // TODO(lpl): Check validation
140        Ok(EcVrfPublicKey(bytes.to_vec()))
141    }
142}
143
144impl TryFrom<&[u8]> for EcVrfProof {
145    type Error = CryptoMaterialError;
146
147    /// Deserialize an EcVrfPrivateKey. This method will also check for key
148    /// validity.
149    fn try_from(
150        bytes: &[u8],
151    ) -> std::result::Result<EcVrfProof, CryptoMaterialError> {
152        // TODO(lpl): Check validation
153        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
205// TODO(lpl): Double check the correctness of key generation.
206// Reuse ec group in VRF_CONTEXT?
207impl 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/// Produces a uniformly random bls keypair from a seed
224#[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}