diem_crypto/
traits.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8//! This module provides a generic set of traits for dealing with cryptographic
9//! primitives.
10//!
11//! For examples on how to use these traits, see the implementations of the
12//! `ed25519` modules.
13
14use crate::{hash::CryptoHash, HashValue};
15use anyhow::Result;
16use core::convert::{From, TryFrom};
17use rand::{rngs::StdRng, CryptoRng, RngCore, SeedableRng};
18use serde::{de::DeserializeOwned, Serialize};
19use std::{fmt::Debug, hash::Hash};
20use thiserror::Error;
21
22/// An error type for key and signature validation issues, see
23/// [`ValidCryptoMaterial`][ValidCryptoMaterial].
24///
25/// This enum reflects there are two interesting causes of validation
26/// failure for the ingestion of key or signature material: deserialization
27/// errors (often, due to mangled material or curve equation failure for ECC)
28/// and validation errors (material recognizable but unacceptable for use,
29/// e.g. unsafe).
30#[derive(Clone, Debug, PartialEq, Eq, Error)]
31#[error("{:?}", self)]
32pub enum CryptoMaterialError {
33    /// Struct to be signed does not serialize correctly.
34    SerializationError,
35    /// Key or signature material does not deserialize correctly.
36    DeserializationError,
37    /// Key or signature material deserializes, but is otherwise not valid.
38    ValidationError,
39    /// Key, threshold or signature material does not have the expected size.
40    WrongLengthError,
41    /// Part of the signature or key is not canonical resulting to malleability
42    /// issues.
43    CanonicalRepresentationError,
44    /// A curve point (i.e., a public key) lies on a small group.
45    SmallSubgroupError,
46    /// A curve point (i.e., a public key) does not satisfy the curve equation.
47    PointNotOnCurveError,
48    /// BitVec errors in accountable multi-sig schemes.
49    BitVecError(String),
50    /// bls aggerate error
51    AggregateError,
52}
53
54/// The serialized length of the data that enables macro derived serialization
55/// and deserialization.
56pub trait Length {
57    /// The serialized length of the data
58    fn length(&self) -> usize;
59}
60
61/// Key or more generally crypto material with a notion of byte validation.
62///
63/// A type family for material that knows how to serialize and
64/// deserialize, as well as validate byte-encoded material. The
65/// validation must be implemented as a [`TryFrom`][TryFrom] which
66/// classifies its failures against the above
67/// [`CryptoMaterialError`][CryptoMaterialError].
68///
69/// This provides an implementation for a validation that relies on a
70/// round-trip to bytes and corresponding [`TryFrom`][TryFrom].
71pub trait ValidCryptoMaterial:
72    // The for<'a> exactly matches the assumption "deserializable from any lifetime".
73    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Serialize + DeserializeOwned
74{
75    /// Convert the valid crypto material to bytes.
76    fn to_bytes(&self) -> Vec<u8>;
77}
78
79/// An extension to to/from Strings for
80/// [`ValidCryptoMaterial`][ValidCryptoMaterial].
81///
82/// Relies on [`hex`][::hex] for string encoding / decoding.
83/// No required fields, provides a default implementation.
84pub trait ValidCryptoMaterialStringExt: ValidCryptoMaterial {
85    /// When trying to convert from bytes, we simply decode the string into
86    /// bytes before checking if we can convert.
87    fn from_encoded_string(
88        encoded_str: &str,
89    ) -> std::result::Result<Self, CryptoMaterialError> {
90        let bytes_out = ::hex::decode(encoded_str);
91        // We defer to `try_from` to make sure we only produce valid crypto
92        // materials.
93        bytes_out
94            // We reinterpret a failure to serialize: key is mangled someway.
95            .or(Err(CryptoMaterialError::DeserializationError))
96            .and_then(|ref bytes| Self::try_from(bytes))
97    }
98    /// A function to encode into hex-string after serializing.
99    fn to_encoded_string(&self) -> Result<String> {
100        Ok(::hex::encode(&self.to_bytes()))
101    }
102}
103
104// There's nothing required in this extension, so let's just derive it
105// for anybody that has a ValidCryptoMaterial.
106impl<T: ValidCryptoMaterial> ValidCryptoMaterialStringExt for T {}
107
108/// A type family for key material that should remain secret and has an
109/// associated type of the [`PublicKey`][PublicKey] family.
110pub trait PrivateKey: Sized {
111    /// We require public / private types to be coupled, i.e. their
112    /// associated type is each other.
113    type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;
114
115    /// Returns the associated public key
116    fn public_key(&self) -> Self::PublicKeyMaterial { self.into() }
117}
118
119/// A type family of valid keys that know how to sign.
120///
121/// This trait has a requirement on a `pub(crate)` marker trait meant to
122/// specifically limit its implementations to the present crate.
123///
124/// A trait for a [`ValidCryptoMaterial`][ValidCryptoMaterial] which knows how
125/// to sign a message, and return an associated `Signature` type.
126pub trait SigningKey:
127    PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial>
128    + ValidCryptoMaterial
129    + private::Sealed
130{
131    /// The associated verifying key type for this signing key.
132    type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
133    /// The associated signature type for this signing key.
134    type SignatureMaterial: Signature<SigningKeyMaterial = Self>;
135
136    /// Signs an object that has an distinct domain-separation hasher and
137    /// that we know how to serialize. There is no pre-hashing into a
138    /// `HashValue` to be done by the caller.
139    ///
140    /// Note: this assumes serialization is unfaillible. See
141    /// diem_common::bcs::ser for a discussion of this assumption.
142    fn sign<T: CryptoHash + Serialize>(
143        &self, message: &T,
144    ) -> Self::SignatureMaterial;
145
146    /// Signs a non-hash input message. For testing only.
147    #[cfg(any(test, feature = "fuzzing"))]
148    fn sign_arbitrary_message(&self, message: &[u8])
149        -> Self::SignatureMaterial;
150
151    /// Returns the associated verifying key
152    fn verifying_key(&self) -> Self::VerifyingKeyMaterial { self.public_key() }
153}
154
155/// A type for key material that can be publicly shared, and in asymmetric
156/// fashion, can be obtained from a [`PrivateKey`][PrivateKey]
157/// reference.
158/// This convertibility requirement ensures the existence of a
159/// deterministic, canonical public key construction from a private key.
160pub trait PublicKey: Sized + Clone + Eq + Hash +
161    // This unsightly turbofish type parameter is the precise constraint
162    // needed to require that there exists an
163    //
164    // ```
165    // impl From<&MyPrivateKeyMaterial> for MyPublicKeyMaterial
166    // ```
167    //
168    // declaration, for any `MyPrivateKeyMaterial`, `MyPublicKeyMaterial`
169    // on which we register (respectively) `PublicKey` and `PrivateKey`
170    // implementations.
171    for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
172    /// We require public / private types to be coupled, i.e. their
173    /// associated type is each other.
174    type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
175}
176
177/// A type family of public keys that are used for signing.
178///
179/// This trait has a requirement on a `pub(crate)` marker trait meant to
180/// specifically limit its implementations to the present crate.
181///
182/// It is linked to a type of the Signature family, which carries the
183/// verification implementation.
184pub trait VerifyingKey:
185    PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial>
186    + ValidCryptoMaterial
187    + private::Sealed
188{
189    /// The associated signing key type for this verifying key.
190    type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
191    /// The associated signature type for this verifying key.
192    type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;
193
194    /// We provide the striaghtfoward implementation which dispatches to the
195    /// signature.
196    fn verify_struct_signature<T: CryptoHash + Serialize>(
197        &self, message: &T, signature: &Self::SignatureMaterial,
198    ) -> Result<()> {
199        signature.verify(message, self)
200    }
201
202    /// We provide the implementation which dispatches to the signature.
203    fn batch_verify<T: CryptoHash + Serialize>(
204        message: &T, keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
205    ) -> Result<()> {
206        Self::SignatureMaterial::batch_verify(message, keys_and_signatures)
207    }
208}
209
210/// A type family for signature material that knows which public key type
211/// is needed to verify it, and given such a public key, knows how to
212/// verify.
213///
214/// This trait simply requires an association to some type of the
215/// [`PublicKey`][PublicKey] family of which we are the `SignatureMaterial`.
216///
217/// This trait has a requirement on a `pub(crate)` marker trait meant to
218/// specifically limit its implementations to the present crate.
219///
220/// It should be possible to write a generic signature function that
221/// checks signature material passed as `&[u8]` and only returns Ok when
222/// that material de-serializes to a signature of the expected concrete
223/// scheme. This would be done as an extension trait of
224/// [`Signature`][Signature].
225pub trait Signature:
226    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError>
227    + Sized
228    + Debug
229    + Clone
230    + Eq
231    + Hash
232    + private::Sealed
233{
234    /// The associated verifying key type for this signature.
235    type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
236    /// The associated signing key type for this signature
237    type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;
238
239    /// Verification for a struct we unabmiguously know how to serialize and
240    /// that we have a domain separation prefix for.
241    fn verify<T: CryptoHash + Serialize>(
242        &self, message: &T, public_key: &Self::VerifyingKeyMaterial,
243    ) -> Result<()>;
244
245    /// Native verification function.
246    fn verify_arbitrary_msg(
247        &self, message: &[u8], public_key: &Self::VerifyingKeyMaterial,
248    ) -> Result<()>;
249
250    /// The implementer can override a batch verification implementation
251    /// that by default iterates over each signature. More efficient
252    /// implementations exist and should be implemented for many schemes.
253    fn batch_verify<T: CryptoHash + Serialize>(
254        message: &T,
255        keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
256    ) -> Result<()> {
257        for (key, signature) in keys_and_signatures {
258            signature.verify(message, &key)?
259        }
260        Ok(())
261    }
262}
263
264/// Public key for VRF
265pub trait VRFPublicKey:
266    PublicKey<PrivateKeyMaterial = <Self as VRFPublicKey>::PrivateKeyMaterial>
267    + ValidCryptoMaterial
268    + private::Sealed
269{
270    /// The associated private key type for this public key.
271    type PrivateKeyMaterial: VRFPrivateKey<PublicKeyMaterial = Self>;
272    /// The associated proof type for this public key.
273    type ProofMaterial: VRFProof<PublicKeyMaterial = Self>;
274
275    /// Verify if `proof` if generated from `seed` by the private key of this
276    /// public key.
277    ///
278    /// If successful, return the VRF hash output.
279    fn verify_proof(
280        &self, seed: &[u8], proof: &Self::ProofMaterial,
281    ) -> Result<HashValue> {
282        proof.verify(seed, &self)
283    }
284}
285
286/// Private key for VRF
287pub trait VRFPrivateKey:
288    PrivateKey<PublicKeyMaterial = <Self as VRFPrivateKey>::PublicKeyMaterial>
289    + ValidCryptoMaterial
290    + private::Sealed
291{
292    /// The associated public key type for this private key.
293    type PublicKeyMaterial: VRFPublicKey<PrivateKeyMaterial = Self>;
294    /// The associated proof type for this private key.
295    type ProofMaterial: VRFProof<PrivateKeyMaterial = Self>;
296
297    /// Generate a random number (hash) with a proof for verification.
298    fn compute(&self, seed: &[u8]) -> Result<Self::ProofMaterial>;
299}
300
301/// The proof of VRF
302pub trait VRFProof:
303    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError>
304    + Sized
305    + Debug
306    + Clone
307    + Eq
308    + Hash
309    + private::Sealed
310{
311    /// The associated public key type for this proof.
312    type PublicKeyMaterial: VRFPublicKey<ProofMaterial = Self>;
313    /// The associated private key type for this proof.
314    type PrivateKeyMaterial: VRFPrivateKey<ProofMaterial = Self>;
315
316    /// Convert the proof to a verifiable random number (hash).
317    fn to_hash(&self) -> Result<HashValue>;
318
319    /// Verify if the proof is generated from `seed` by the private key of
320    /// `public_key`.
321    ///
322    /// If successful, return the VRF hash output.
323    fn verify(
324        &self, seed: &[u8], public_key: &Self::PublicKeyMaterial,
325    ) -> Result<HashValue>;
326}
327
328/// A type family for schemes which know how to generate key material from
329/// a cryptographically-secure [`CryptoRng`][::rand::CryptoRng].
330pub trait Uniform {
331    /// Generate key material from an RNG. This should generally not be used for
332    /// production purposes even with a good source of randomness. When
333    /// possible use hardware crypto to generate and store private keys.
334    fn generate<R>(rng: &mut R) -> Self
335    where R: RngCore + CryptoRng;
336
337    /// Generate a random key using the shared TEST_SEED
338    fn generate_for_testing() -> Self
339    where Self: Sized {
340        let mut rng: StdRng =
341            SeedableRng::from_seed(crate::test_utils::TEST_SEED);
342        Self::generate(&mut rng)
343    }
344}
345
346/// A type family with a by-convention notion of genesis private key.
347pub trait Genesis: PrivateKey {
348    /// Produces the genesis private key.
349    fn genesis() -> Self;
350}
351
352/// The trait for VDF.
353pub trait VerifiableDelayFunction {
354    /// solve inputted `challenge` with a given `difficulty`, and output a
355    /// solution.
356    fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>>;
357
358    /// Verify that the given `alleged_solution` is indeed a valid solution.
359    fn verify(
360        &self, challenge: &[u8], difficulty: u64, alleged_solution: &[u8],
361    ) -> Result<()>;
362}
363
364/// A pub(crate) mod hiding a Sealed trait and its implementations, allowing
365/// us to make sure implementations are constrained to the crypto crate.
366// See https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
367pub(crate) mod private {
368    pub trait Sealed {}
369
370    // Implement for the ed25519, multi-ed25519 signatures
371    impl Sealed for crate::ed25519::Ed25519PrivateKey {}
372    impl Sealed for crate::ed25519::Ed25519PublicKey {}
373    impl Sealed for crate::ed25519::Ed25519Signature {}
374
375    impl Sealed for crate::multi_ed25519::MultiEd25519PrivateKey {}
376    impl Sealed for crate::multi_ed25519::MultiEd25519PublicKey {}
377    impl Sealed for crate::multi_ed25519::MultiEd25519Signature {}
378
379    impl Sealed for crate::bls::BLSPublicKey {}
380    impl Sealed for crate::bls::BLSPrivateKey {}
381    impl Sealed for crate::bls::BLSSignature {}
382
383    impl Sealed for crate::multi_bls::MultiBLSPublicKey {}
384    impl Sealed for crate::multi_bls::MultiBLSPrivateKey {}
385    impl Sealed for crate::multi_bls::MultiBLSSignature {}
386
387    impl Sealed for crate::ec_vrf::EcVrfPublicKey {}
388    impl Sealed for crate::ec_vrf::EcVrfPrivateKey {}
389    impl Sealed for crate::ec_vrf::EcVrfProof {}
390}
391
392/// Hash the vrf output and a nonce within the proposer's voting power to
393/// compute a hash value as its priority.
394/// This is used in both choosing leaders in a round and electing committees in
395/// a term.
396pub fn vrf_number_with_nonce(vrf_output: &HashValue, nonce: u64) -> HashValue {
397    HashValue::sha3_256_of(
398        &[vrf_output.as_ref() as &[u8], &nonce.to_be_bytes()].concat(),
399    )
400}