vrf_wasm/
traits.rs

1// Copyright (c) 2021, Facebook, Inc. and its affiliates
2// Copyright (c) 2022, Mysten Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use rand_core::{CryptoRng, RngCore};
6use serde::{de::DeserializeOwned, Serialize};
7use std::{
8    borrow::Borrow,
9    fmt::{Debug, Display},
10    str::FromStr,
11};
12use crate::error::FastCryptoResult;
13use crate::{
14    encoding::{Base64, Encoding},
15    error::FastCryptoError,
16    hash::HashFunction,
17};
18// Import RNG implementations from the rng module
19pub use crate::rng::{WasmRng, WasmRngFromSeed};
20
21/// Trait impl'd by concrete types that represent digital cryptographic material
22/// (keys).
23///
24/// Key types *must* (as mandated by the `AsRef<[u8]>` bound) be a thin
25/// wrapper around the "bag-of-bytes" serialized form of a key which can
26/// be directly parsed from or written to the "wire".
27///
28/// The [`ToFromBytes`] trait aims to provide similar simplicity by minimizing
29/// the number of steps involved to obtain a serializable key and
30/// ideally ensuring there is one signature type for any given signature system
31/// shared by all "provider" crates.
32///
33/// For signature systems which require a more advanced internal representation
34/// (e.g. involving decoded scalars or decompressed elliptic curve points) it's
35/// recommended that "provider" libraries maintain their own internal signature
36/// type and use `From` bounds to provide automatic conversions.
37///
38pub trait ToFromBytes: AsRef<[u8]> + Debug + Sized {
39    /// Parse an object from its byte representation
40    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError>;
41
42    /// Borrow a byte slice representing the serialized form of this object
43    fn as_bytes(&self) -> &[u8] {
44        self.as_ref()
45    }
46}
47
48/// Cryptographic material with an immediate conversion to/from Base64 strings.
49///
50/// This is an [extension trait](https://rust-lang.github.io/rfcs/0445-extension-trait-conventions.html) of `ToFromBytes` above.
51///
52pub trait EncodeDecodeBase64: Sized {
53    fn encode_base64(&self) -> String;
54    fn decode_base64(value: &str) -> FastCryptoResult<Self>;
55}
56
57impl<T: ToFromBytes> EncodeDecodeBase64 for T {
58    fn encode_base64(&self) -> String {
59        Base64::encode(self.as_bytes())
60    }
61
62    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
63        let bytes = Base64::decode(value)?;
64        <T as ToFromBytes>::from_bytes(&bytes)
65    }
66}
67
68/// Trait impl'd by public keys in asymmetric cryptography.
69///
70/// The trait bounds are implemented so as to be symmetric and equivalent
71/// to the ones on its associated types for private and signature material.
72///
73pub trait VerifyingKey:
74    Serialize
75    + DeserializeOwned
76    + std::hash::Hash
77    + Display
78    + Eq  // required to make some cached bytes representations explicit.
79    + Ord // required to put keys in BTreeMap.
80    + ToFromBytes
81    + for<'a> From<&'a Self::PrivKey> // conversion PrivateKey -> PublicKey.
82    + Send
83    + Sync
84    + 'static
85    + Clone
86{
87    type PrivKey: SigningKey<PubKey=Self>;
88    type Sig: Authenticator<PubKey=Self>;
89    const LENGTH: usize;
90
91    /// Use Self to verify that the provided signature for a given message bytestring is authentic.
92    /// Returns Error if it is inauthentic, or otherwise returns ().
93    fn verify(&self, msg: &[u8], signature: &Self::Sig) -> Result<(), FastCryptoError>;
94
95    // Expected to be overridden by implementations
96    /// Batch verification over the same message. Implementations of this method can be fast,
97    /// assuming rogue key checks have already been performed.
98    /// TODO: take as input a flag to denote if rogue key protection already took place.
99    ///
100    /// # Example
101    /// ```rust,ignore
102    /// use fastcrypto::ed25519::*;
103    /// # use fastcrypto::{traits::{AggregateAuthenticator, KeyPair, Signer, VerifyingKey}};
104    /// use rand::thread_rng;
105    /// let message: &[u8] = b"Hello, world!";
106    /// let kp1 = Ed25519KeyPair::generate(&mut thread_rng());
107    /// let signature1 = kp1.sign(message);
108    /// let kp2 = Ed25519KeyPair::generate(&mut thread_rng());
109    /// let signature2 = kp2.sign(message);
110    /// let public_keys = [kp1.public().clone(), kp2.public().clone()];
111    /// let signatures = [signature1.clone(), signature2.clone()];
112    /// assert!(Ed25519PublicKey::verify_batch_empty_fail(message, &public_keys, &signatures).is_ok());
113    /// ```
114    #[cfg(any(test))]
115    fn verify_batch_empty_fail(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> FastCryptoResult<()> {
116        if sigs.is_empty() || pks.len() != sigs.len() {
117            return Err(FastCryptoError::InvalidInput);
118        }
119        pks.iter()
120            .zip(sigs)
121            .try_for_each(|(pk, sig)| pk.verify(msg, sig))
122    }
123
124    // Expected to be overridden by implementations
125    /// Batch verification over different messages. Implementations of this method can be fast,
126    /// assuming rogue key checks have already been performed.
127    /// TODO: take as input a flag to denote if rogue key protection already took place.
128    ///
129    /// # Example
130    /// ```rust,ignore
131    /// use fastcrypto::ed25519::*;
132    /// # use fastcrypto::traits::{AggregateAuthenticator, KeyPair, Signer, VerifyingKey};
133    /// use rand::thread_rng;
134    /// let message1: &[u8] = b"Hello, world!";
135    /// let kp1 = Ed25519KeyPair::generate(&mut thread_rng());
136    /// let signature1 = kp1.sign(message1);
137    /// let message2: &[u8] = b"Hello, world!!!";
138    /// let kp2 = Ed25519KeyPair::generate(&mut thread_rng());
139    /// let signature2 = kp2.sign(message2);
140    /// let messages = [message1, message2];
141    /// let public_keys = [kp1.public().clone(), kp2.public().clone()];
142    /// let signatures = [signature1.clone(), signature2.clone()];
143    /// assert!(Ed25519PublicKey::verify_batch_empty_fail_different_msg(&messages, &public_keys, &signatures).is_ok());
144    /// ```
145    #[cfg(any(test))]
146    fn verify_batch_empty_fail_different_msg<'a, M>(msgs: &[M], pks: &[Self], sigs: &[Self::Sig])
147        -> FastCryptoResult<()> where M: Borrow<[u8]> + 'a {
148        if sigs.is_empty() || pks.len() != sigs.len() || pks.len() != msgs.len() {
149            return Err(FastCryptoError::InvalidInput);
150        }
151        pks.iter()
152            .zip(sigs)
153            .zip(msgs)
154            .try_for_each(|((pk, sig), msg)| pk.verify(msg.borrow(), sig))
155    }
156}
157
158/// Trait impl'd by private (secret) keys in asymmetric cryptography.
159///
160/// The trait bounds are implemented so as to be symmetric and equivalent
161/// to the ones on its associated types for public key and signature material.
162///
163pub trait SigningKey: ToFromBytes + Serialize + DeserializeOwned + Send + Sync + 'static {
164    type PubKey: VerifyingKey<PrivKey = Self>;
165    type Sig: Authenticator<PrivKey = Self>;
166    const LENGTH: usize;
167}
168
169/// Trait impl'd by signatures in asymmetric cryptography.
170///
171/// The trait bounds are implemented so as to be symmetric and equivalent
172/// to the ones on its associated types for private key and public key material.
173///
174pub trait Authenticator:
175    ToFromBytes + Display + Serialize + DeserializeOwned + Send + Sync + 'static + Clone
176{
177    type PubKey: VerifyingKey<Sig = Self>;
178    type PrivKey: SigningKey<Sig = Self>;
179    const LENGTH: usize;
180}
181
182/// Trait impl'd by a key/keypair that can create signatures.
183///
184pub trait Signer<Sig> {
185    /// Create a new signature over a message.
186    fn sign(&self, msg: &[u8]) -> Sig;
187}
188
189/// Trait impl'd by a public / private key pair in asymmetric cryptography.
190///
191pub trait KeyPair:
192    Sized + From<Self::PrivKey> + Signer<Self::Sig> + EncodeDecodeBase64 + FromStr
193{
194    type PubKey: VerifyingKey<PrivKey = Self::PrivKey, Sig = Self::Sig>;
195    type PrivKey: SigningKey<PubKey = Self::PubKey, Sig = Self::Sig>;
196    type Sig: Authenticator<PubKey = Self::PubKey, PrivKey = Self::PrivKey>;
197
198    /// Get the public key.
199    fn public(&'_ self) -> &'_ Self::PubKey;
200    /// Get the private key.
201    fn private(self) -> Self::PrivKey;
202
203    // fn copy(&self) -> Self;
204
205    /// Generate a new keypair using the given RNG.
206    fn generate<R: AllowedRng>(rng: &mut R) -> Self;
207}
208
209/// Trait impl'd by public / private keypairs that can generate recoverable signatures
210pub trait RecoverableSigner {
211    type PubKey;
212    type Sig: RecoverableSignature<Signer = Self, PubKey = Self::PubKey>;
213
214    /// Sign as a recoverable signature.
215    fn sign_recoverable(&self, msg: &[u8]) -> Self::Sig {
216        self.sign_recoverable_with_hash::<<<Self as RecoverableSigner>::Sig as RecoverableSignature>::DefaultHash>(msg)
217    }
218
219    /// Sign as a recoverable signature using the given hash function.
220    ///
221    /// Note: This is currently only used for Secp256r1 and Secp256k1 where the hash function must have 32 byte output.
222    fn sign_recoverable_with_hash<H: HashFunction<32>>(&self, msg: &[u8]) -> Self::Sig;
223}
224
225pub trait VerifyRecoverable: Eq + Sized {
226    type Sig: RecoverableSignature<PubKey = Self>;
227
228    /// Verify a recoverable signature by recovering the public key and compare it to self.
229    fn verify_recoverable(&self, msg: &[u8], signature: &Self::Sig) -> Result<(), FastCryptoError> {
230        self.verify_recoverable_with_hash::<<<Self as VerifyRecoverable>::Sig as RecoverableSignature>::DefaultHash>(msg, signature)
231    }
232
233    /// Verify a recoverable signature by recovering the public key and compare it to self.
234    /// The recovery is using the given hash function.
235    ///
236    /// Note: This is currently only used for Secp256r1 and Secp256k1 where the hash function must have 32 byte output.
237    fn verify_recoverable_with_hash<H: HashFunction<32>>(
238        &self,
239        msg: &[u8],
240        signature: &Self::Sig,
241    ) -> Result<(), FastCryptoError> {
242        match signature.recover_with_hash::<H>(msg)? == *self {
243            true => Ok(()),
244            false => Err(FastCryptoError::InvalidSignature),
245        }
246    }
247}
248
249/// Trait impl'd by recoverable signatures
250pub trait RecoverableSignature: Sized {
251    type PubKey;
252    type Signer: RecoverableSigner<Sig = Self, PubKey = Self::PubKey>;
253    type DefaultHash: HashFunction<32>;
254
255    /// Recover the public key from this signature.
256    fn recover(&self, msg: &[u8]) -> Result<Self::PubKey, FastCryptoError> {
257        self.recover_with_hash::<Self::DefaultHash>(msg)
258    }
259
260    /// Recover the public key from this signature. Assuming that the given hash function was used for signing.
261    ///
262    /// Note: This is currently only used for Secp256r1 and Secp256k1 where the hash function must have 32 byte output.
263    fn recover_with_hash<H: HashFunction<32>>(
264        &self,
265        msg: &[u8],
266    ) -> Result<Self::PubKey, FastCryptoError>;
267}
268
269/// Trait impl'd by aggregated signatures in asymmetric cryptography.
270///
271/// The trait bounds are implemented to allow the aggregation of multiple signatures,
272/// and to verify it against multiple, unaggregated public keys. For signature schemes
273/// where aggregation is not possible, a trivial implementation is provided.
274///
275pub trait AggregateAuthenticator:
276    Display + Serialize + DeserializeOwned + Send + Sync + 'static + Clone
277{
278    type Sig: Authenticator<PubKey = Self::PubKey>;
279    type PubKey: VerifyingKey<Sig = Self::Sig>;
280    type PrivKey: SigningKey<Sig = Self::Sig>;
281
282    /// Combine signatures into a single aggregated signature.
283    fn aggregate<'a, K: Borrow<Self::Sig> + 'a, I: IntoIterator<Item = &'a K>>(
284        signatures: I,
285    ) -> Result<Self, FastCryptoError>;
286
287    fn add_signature(&mut self, signature: Self::Sig) -> Result<(), FastCryptoError>;
288    fn add_aggregate(&mut self, signature: Self) -> Result<(), FastCryptoError>;
289
290    /// Verify this aggregate signature assuming that all signatures are over the same message.
291    ///
292    /// # Example
293    /// ```rust,ignore
294    /// use fastcrypto::{traits::{AggregateAuthenticator, KeyPair, Signer, VerifyingKey}};
295    /// use rand::thread_rng;
296    /// use fastcrypto::bls12381::min_sig::{BLS12381AggregateSignature, BLS12381KeyPair};
297    ///
298    /// let message: &[u8] = b"Hello, world!";
299    /// let kp1 = BLS12381KeyPair::generate(&mut thread_rng());
300    /// let signature1 = kp1.sign(message);
301    /// let kp2 = BLS12381KeyPair::generate(&mut thread_rng());
302    /// let signature2 = kp2.sign(message);
303    ///
304    /// let aggregated_signature = BLS12381AggregateSignature::aggregate(vec!(&signature1, &signature2)).unwrap();
305    /// let public_keys = &[kp1.public().clone(), kp2.public().clone()];
306    /// assert!(aggregated_signature.verify(public_keys, message).is_ok());
307    /// ```
308    fn verify(
309        &self,
310        pks: &[<Self::Sig as Authenticator>::PubKey],
311        message: &[u8],
312    ) -> Result<(), FastCryptoError>;
313
314    /// Verify this aggregate signature where the signatures are over different messages.
315    ///
316    /// # Example
317    /// ```rust,ignore
318    /// use fastcrypto::{traits::{AggregateAuthenticator, KeyPair, Signer, VerifyingKey}};
319    /// use rand::thread_rng;
320    /// use fastcrypto::bls12381::min_sig::{BLS12381AggregateSignature, BLS12381KeyPair};
321    ///
322    /// let message1: &[u8] = b"Hello, world!";
323    /// let kp1 = BLS12381KeyPair::generate(&mut thread_rng());
324    /// let signature1 = kp1.sign(message1);
325    /// let message2: &[u8] = b"Hello, world!!!";
326    /// let kp2 = BLS12381KeyPair::generate(&mut thread_rng());
327    /// let signature2 = kp2.sign(message2);
328    ///
329    /// let aggregated_signature = BLS12381AggregateSignature::aggregate(vec!(&signature1, &signature2)).unwrap();
330    /// let messages = [message1, message2];
331    /// let public_keys = [kp1.public().clone(), kp2.public().clone()];
332    /// assert!(aggregated_signature.verify_different_msg(&public_keys, &messages).is_ok());
333    /// ```
334    fn verify_different_msg(
335        &self,
336        pks: &[<Self::Sig as Authenticator>::PubKey],
337        messages: &[&[u8]],
338    ) -> Result<(), FastCryptoError>;
339
340    /// Verify a batch of aggregate signatures, each consisting of a number of signatures over the same message.
341    ///
342    /// # Example
343    /// ```rust,ignore
344    /// use fastcrypto::{traits::{AggregateAuthenticator, KeyPair, Signer, VerifyingKey}};
345    /// use rand::thread_rng;
346    /// use fastcrypto::bls12381::min_sig::{BLS12381AggregateSignature, BLS12381KeyPair};
347    ///
348    /// let message1: &[u8] = b"Hello, world!";
349    /// let kp1 = BLS12381KeyPair::generate(&mut thread_rng());
350    /// let signature1 = kp1.sign(message1);
351    /// let aggregated_signature1 = BLS12381AggregateSignature::aggregate(vec!(&signature1)).unwrap();
352    /// let message2: &[u8] = b"1234";
353    /// let kp2 = BLS12381KeyPair::generate(&mut thread_rng());
354    /// let signature2 = kp2.sign(message2);
355    /// let aggregated_signature2 = BLS12381AggregateSignature::aggregate(vec!(&signature2)).unwrap();
356    ///
357    /// let aggregated_signatures = [&aggregated_signature1, &aggregated_signature2];
358    /// let messages = [message1, message2];
359    /// let pks1 = [kp1.public().clone()];
360    /// let pks2 = [kp2.public().clone()];
361    /// let public_keys = vec!(pks1.iter(), pks2.iter());
362    /// assert!(BLS12381AggregateSignature::batch_verify(&aggregated_signatures, public_keys, &messages).is_ok());
363    /// ```
364    fn batch_verify<'a>(
365        sigs: &[&Self],
366        pks: Vec<impl ExactSizeIterator<Item = &'a Self::PubKey>>,
367        messages: &[&[u8]],
368    ) -> Result<(), FastCryptoError>;
369}
370
371/// Trait impl'd by cryptographic material that can be generated randomly such as keys and nonces.
372///
373pub trait Generate {
374    /// Generate a new random instance using the given RNG.
375    fn generate<R: AllowedRng>(rng: &mut R) -> Self;
376}
377
378/// Trait impl'd by a keys/secret seeds for generating a secure instance.
379///
380pub trait FromUniformBytes<const LENGTH: usize>: ToFromBytes {
381    fn generate<R: AllowedRng>(rng: &mut R) -> Self {
382        let mut bytes = [0u8; LENGTH];
383        rng.fill_bytes(&mut bytes);
384        Self::from_bytes(&bytes).unwrap()
385    }
386}
387
388/// Trait for objects that support an insecure default value that should **only** be used as a
389/// placeholder.
390pub trait InsecureDefault {
391    fn insecure_default() -> Self;
392}
393
394// Whitelist the RNG our APIs accept (see https://rust-random.github.io/book/guide-rngs.html for
395// others).
396/// Trait impl'd by RNG's accepted by vrf-wasm.
397pub trait AllowedRng: CryptoRng + RngCore {}
398
399// Implement AllowedRng for ChaCha20Rng once to avoid conflicts
400impl AllowedRng for rand_chacha::ChaCha20Rng {}