commonware_cryptography/
lib.rs

1//! Generate keys, sign arbitrary messages, and deterministically verify signatures.
2//!
3//! # Status
4//!
5//! `commonware-cryptography` is **ALPHA** software and is not yet recommended for production use. Developers should
6//! expect breaking changes and occasional instability.
7
8use commonware_utils::Array;
9use rand::{CryptoRng, Rng, RngCore, SeedableRng};
10use std::fmt::Debug;
11use thiserror::Error;
12
13pub mod bls12381;
14pub use bls12381::Bls12381;
15pub mod ed25519;
16pub use ed25519::{Ed25519, Ed25519Batch};
17pub mod sha256;
18pub use sha256::{hash, Sha256};
19pub mod secp256r1;
20pub use secp256r1::Secp256r1;
21
22/// Errors that can occur when interacting with cryptographic primitives.
23#[derive(Error, Debug, PartialEq)]
24pub enum Error {
25    #[error("invalid digest length")]
26    InvalidDigestLength,
27    #[error("invalid private key")]
28    InvalidPrivateKey,
29    #[error("invalid private key length")]
30    InvalidPrivateKeyLength,
31    #[error("invalid public key")]
32    InvalidPublicKey,
33    #[error("invalid public key length")]
34    InvalidPublicKeyLength,
35    #[error("invalid signature")]
36    InvalidSignature,
37    #[error("invalid signature length")]
38    InvalidSignatureLength,
39}
40
41/// Any implementation of a cryptographic primitive must specify a `PublicKey` and `Signature`.
42pub trait Specification {
43    /// Public key used for verifying signatures.
44    type PublicKey: Array;
45    /// Signature generated by signing a message.
46    type Signature: Array;
47}
48
49/// Implementation that can verify that a `PublicKey` produced a valid `Signature`.
50pub trait Verifier: Specification + Clone + Send + Sync + 'static {
51    /// Check that a signature is valid for the given message and public key.
52    ///
53    /// The message should not be hashed prior to calling this function. If a particular
54    /// scheme requires a payload to be hashed before it is signed, it will be done internally.
55    ///
56    /// Because namespace is prepended to message before signing, the namespace provided here must
57    /// match the namespace provided during signing.
58    fn verify(
59        namespace: Option<&[u8]>,
60        message: &[u8],
61        public_key: &Self::PublicKey,
62        signature: &Self::Signature,
63    ) -> bool;
64}
65
66/// Implementation that can sign a message with a `PrivateKey`.
67pub trait Signer: Specification + Clone + Send + Sync + 'static {
68    /// Private key used for signing.
69    type PrivateKey: Array;
70
71    /// Returns a new instance of the scheme.
72    fn new<R: Rng + CryptoRng>(rng: &mut R) -> Self;
73
74    /// Sign the given message.
75    ///
76    /// The message should not be hashed prior to calling this function. If a particular scheme
77    /// requires a payload to be hashed before it is signed, it will be done internally.
78    ///
79    /// A namespace should be used to prevent replay attacks. It will be prepended to the message so
80    /// that a signature meant for one context cannot be used unexpectedly in another (i.e. signing
81    /// a message on the network layer can't accidentally spend funds on the execution layer). See
82    /// [union_unique](commonware_utils::union_unique) for details.
83    fn sign(&mut self, namespace: Option<&[u8]>, message: &[u8]) -> Self::Signature;
84
85    /// Returns a new instance of the scheme from a secret key.
86    fn from(private_key: Self::PrivateKey) -> Option<Self>;
87
88    /// Returns a new instance of the scheme from a provided seed.
89    ///
90    /// # Warning
91    ///
92    /// This function is insecure and should only be used for examples
93    /// and testing.
94    fn from_seed(seed: u64) -> Self {
95        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
96        Self::new(&mut rng)
97    }
98
99    /// Returns the private key of the signer.
100    fn private_key(&self) -> Self::PrivateKey;
101
102    /// Returns the public key of the signer.
103    fn public_key(&self) -> Self::PublicKey;
104}
105
106/// Implementation that can both sign and verify messages.
107pub trait Scheme: Signer + Verifier {}
108
109/// Blanket implementation of the `Scheme` trait for types that implement both the `Signer` and `Verifier` traits.
110impl<T> Scheme for T where T: Signer + Verifier {}
111
112/// Implementation that can indicate whether all `Signatures` are correct or that some `Signature`
113/// is incorrect.
114pub trait BatchScheme: Specification {
115    /// Create a new batch scheme.
116    fn new() -> Self;
117
118    /// Append item to the batch.
119    ///
120    /// The message should not be hashed prior to calling this function. If a particular scheme
121    /// requires a payload to be hashed before it is signed, it will be done internally.
122    ///
123    /// A namespace should be used to prevent replay attacks. It will be prepended to the message so
124    /// that a signature meant for one context cannot be used unexpectedly in another (i.e. signing
125    /// a message on the network layer can't accidentally spend funds on the execution layer). See
126    /// [union_unique](commonware_utils::union_unique) for details.
127    fn add(
128        &mut self,
129        namespace: Option<&[u8]>,
130        message: &[u8],
131        public_key: &Self::PublicKey,
132        signature: &Self::Signature,
133    ) -> bool;
134
135    /// Verify all items added to the batch.
136    ///
137    /// Returns `true` if all items are valid, `false` otherwise.
138    ///
139    /// # Why Randomness?
140    ///
141    /// When performing batch verification, it is often important to add some randomness
142    /// to prevent an attacker from constructing a malicious batch of signatures that pass
143    /// batch verification but are invalid individually. Abstractly, think of this as
144    /// there existing two valid signatures (`c_1` and `c_2`) and an attacker proposing
145    /// (`c_1 + d` and `c_2 - d`).
146    ///
147    /// You can read more about this [here](https://ethresear.ch/t/security-of-bls-batch-verification/10748#the-importance-of-randomness-4).
148    fn verify<R: RngCore + CryptoRng>(self, rng: &mut R) -> bool;
149}
150
151/// Specializes the [commonware_utils::Array] trait with the Copy trait for cryptographic digests
152/// (which should be cheap to clone).
153pub trait Digest: Array + Copy {}
154
155/// An object that can generate a digest.
156pub trait Digestible<D: Digest>: Clone + Send + Sync + 'static {
157    /// Generate a digest from the object.
158    fn digest(&self) -> D;
159}
160
161/// Interface that commonware crates rely on for hashing.
162///
163/// Hash functions in commonware primitives are not typically hardcoded
164/// to a specific algorithm (e.g. SHA-256) because different hash functions
165/// may work better with different cryptographic schemes, may be more efficient
166/// to use in STARK/SNARK proofs, or provide different levels of security (with some
167/// performance/size penalty).
168///
169/// This trait is required to implement the `Clone` trait because it is often
170/// part of a struct that is cloned. In practice, implementations do not actually
171/// clone the hasher state but users should not rely on this behavior and call `reset`
172/// after cloning.
173pub trait Hasher: Clone + Send + Sync + 'static {
174    /// Digest generated by the hasher.
175    type Digest: Digest;
176
177    /// Create a new hasher.
178    fn new() -> Self;
179
180    /// Append message to previously recorded data.
181    fn update(&mut self, message: &[u8]);
182
183    /// Hash all recorded data and reset the hasher
184    /// to the initial state.
185    fn finalize(&mut self) -> Self::Digest;
186
187    /// Reset the hasher without generating a hash.
188    ///
189    /// This function does not need to be called after `finalize`.
190    fn reset(&mut self);
191
192    /// Generate a random digest.
193    ///
194    /// # Warning
195    ///
196    /// This function is typically used for testing and is not recommended
197    /// for production use.
198    fn random<R: Rng + CryptoRng>(rng: &mut R) -> Self::Digest;
199}
200
201#[cfg(test)]
202mod tests {
203    use super::*;
204    use commonware_codec::SizedCodec;
205    use rand::rngs::OsRng;
206
207    fn test_validate<C: Scheme>() {
208        let signer = C::new(&mut OsRng);
209        let public_key = signer.public_key();
210        assert!(C::PublicKey::try_from(public_key.as_ref()).is_ok());
211    }
212
213    fn test_from_valid_private_key<C: Scheme>() {
214        let signer = C::new(&mut OsRng);
215        let private_key = signer.private_key();
216        let public_key = signer.public_key();
217        let signer = C::from(private_key).unwrap();
218        assert_eq!(public_key, signer.public_key());
219    }
220
221    fn test_validate_invalid_public_key<C: Signer>()
222    where
223        C::PublicKey: TryFrom<Vec<u8>, Error = Error>,
224    {
225        let result = C::PublicKey::try_from(vec![0; 1024]);
226        assert_eq!(result, Err(Error::InvalidPublicKeyLength));
227    }
228
229    fn test_sign_and_verify<C: Scheme>() {
230        let mut signer = C::from_seed(0);
231        let namespace = Some(&b"test_namespace"[..]);
232        let message = b"test_message";
233        let signature = signer.sign(namespace, message);
234        let public_key = signer.public_key();
235        assert!(C::verify(namespace, message, &public_key, &signature));
236    }
237
238    fn test_sign_and_verify_wrong_message<C: Scheme>() {
239        let mut signer = C::from_seed(0);
240        let namespace: Option<&[u8]> = Some(&b"test_namespace"[..]);
241        let message = b"test_message";
242        let wrong_message = b"wrong_message";
243        let signature = signer.sign(namespace, message);
244        let public_key = signer.public_key();
245        assert!(!C::verify(
246            namespace,
247            wrong_message,
248            &public_key,
249            &signature
250        ));
251    }
252
253    fn test_sign_and_verify_wrong_namespace<C: Scheme>() {
254        let mut signer = C::from_seed(0);
255        let namespace = Some(&b"test_namespace"[..]);
256        let wrong_namespace = Some(&b"wrong_namespace"[..]);
257        let message = b"test_message";
258        let signature = signer.sign(namespace, message);
259        let public_key = signer.public_key();
260        assert!(!C::verify(
261            wrong_namespace,
262            message,
263            &public_key,
264            &signature
265        ));
266    }
267
268    fn test_empty_vs_none_namespace<C: Scheme>() {
269        let mut signer = C::from_seed(0);
270        let empty_namespace = Some(&b""[..]);
271        let message = b"test_message";
272        let signature = signer.sign(empty_namespace, message);
273        let public_key = signer.public_key();
274        assert!(C::verify(empty_namespace, message, &public_key, &signature));
275        assert!(!C::verify(None, message, &public_key, &signature));
276    }
277
278    fn test_signature_determinism<C: Scheme>() {
279        let mut signer_1 = C::from_seed(0);
280        let mut signer_2 = C::from_seed(0);
281        let namespace = Some(&b"test_namespace"[..]);
282        let message = b"test_message";
283        let signature_1 = signer_1.sign(namespace, message);
284        let signature_2 = signer_2.sign(namespace, message);
285        assert_eq!(signer_1.public_key(), signer_2.public_key());
286        assert_eq!(signature_1, signature_2);
287    }
288
289    fn test_invalid_signature_publickey_pair<C: Scheme>() {
290        let mut signer = C::from_seed(0);
291        let signer_2 = C::from_seed(1);
292        let namespace = Some(&b"test_namespace"[..]);
293        let message = b"test_message";
294        let signature = signer.sign(namespace, message);
295        let public_key = signer_2.public_key();
296        assert!(!C::verify(namespace, message, &public_key, &signature));
297    }
298
299    #[test]
300    fn test_ed25519_validate() {
301        test_validate::<Ed25519>();
302    }
303
304    #[test]
305    fn test_ed25519_validate_invalid_public_key() {
306        test_validate_invalid_public_key::<Ed25519>();
307    }
308
309    #[test]
310    fn test_ed25519_from_valid_private_key() {
311        test_from_valid_private_key::<Ed25519>();
312    }
313
314    #[test]
315    fn test_ed25519_sign_and_verify() {
316        test_sign_and_verify::<Ed25519>();
317    }
318
319    #[test]
320    fn test_ed25519_sign_and_verify_wrong_message() {
321        test_sign_and_verify_wrong_message::<Ed25519>();
322    }
323
324    #[test]
325    fn test_ed25519_sign_and_verify_wrong_namespace() {
326        test_sign_and_verify_wrong_namespace::<Ed25519>();
327    }
328
329    #[test]
330    fn test_ed25519_empty_vs_none_namespace() {
331        test_empty_vs_none_namespace::<Ed25519>();
332    }
333
334    #[test]
335    fn test_ed25519_signature_determinism() {
336        test_signature_determinism::<Ed25519>();
337    }
338
339    #[test]
340    fn test_ed25519_invalid_signature_publickey_pair() {
341        test_invalid_signature_publickey_pair::<Ed25519>();
342    }
343
344    #[test]
345    fn test_ed25519_len() {
346        assert_eq!(<Ed25519 as Specification>::PublicKey::LEN_ENCODED, 32);
347        assert_eq!(<Ed25519 as Specification>::Signature::LEN_ENCODED, 64);
348    }
349
350    #[test]
351    fn test_bls12381_validate() {
352        test_validate::<Bls12381>();
353    }
354
355    #[test]
356    fn test_bls12381_validate_invalid_public_key() {
357        test_validate_invalid_public_key::<Bls12381>();
358    }
359
360    #[test]
361    fn test_bls12381_from_valid_private_key() {
362        test_from_valid_private_key::<Bls12381>();
363    }
364
365    #[test]
366    fn test_bls12381_sign_and_verify() {
367        test_sign_and_verify::<Bls12381>();
368    }
369
370    #[test]
371    fn test_bls12381_sign_and_verify_wrong_message() {
372        test_sign_and_verify_wrong_message::<Bls12381>();
373    }
374
375    #[test]
376    fn test_bls12381_sign_and_verify_wrong_namespace() {
377        test_sign_and_verify_wrong_namespace::<Bls12381>();
378    }
379
380    #[test]
381    fn test_bls12381_empty_vs_none_namespace() {
382        test_empty_vs_none_namespace::<Bls12381>();
383    }
384
385    #[test]
386    fn test_bls12381_signature_determinism() {
387        test_signature_determinism::<Bls12381>();
388    }
389
390    #[test]
391    fn test_bls12381_invalid_signature_publickey_pair() {
392        test_invalid_signature_publickey_pair::<Bls12381>();
393    }
394
395    #[test]
396    fn test_bls12381_len() {
397        assert_eq!(<Bls12381 as Specification>::PublicKey::LEN_ENCODED, 48);
398        assert_eq!(<Bls12381 as Specification>::Signature::LEN_ENCODED, 96);
399    }
400
401    #[test]
402    fn test_secp256r1_validate() {
403        test_validate::<Secp256r1>();
404    }
405
406    #[test]
407    fn test_secp256r1_validate_invalid_public_key() {
408        test_validate_invalid_public_key::<Secp256r1>();
409    }
410
411    #[test]
412    fn test_secp256r1_from_valid_private_key() {
413        test_from_valid_private_key::<Secp256r1>();
414    }
415
416    #[test]
417    fn test_secp256r1_sign_and_verify() {
418        test_sign_and_verify::<Secp256r1>();
419    }
420
421    #[test]
422    fn test_secp256r1_sign_and_verify_wrong_message() {
423        test_sign_and_verify_wrong_message::<Secp256r1>();
424    }
425
426    #[test]
427    fn test_secp256r1_sign_and_verify_wrong_namespace() {
428        test_sign_and_verify_wrong_namespace::<Secp256r1>();
429    }
430
431    #[test]
432    fn test_secp256r1_empty_vs_none_namespace() {
433        test_empty_vs_none_namespace::<Secp256r1>();
434    }
435
436    #[test]
437    fn test_secp256r1_signature_determinism() {
438        test_signature_determinism::<Secp256r1>();
439    }
440
441    #[test]
442    fn test_secp256r1_invalid_signature_publickey_pair() {
443        test_invalid_signature_publickey_pair::<Secp256r1>();
444    }
445
446    #[test]
447    fn test_secp256r1_len() {
448        assert_eq!(<Secp256r1 as Specification>::PublicKey::LEN_ENCODED, 33);
449        assert_eq!(<Secp256r1 as Specification>::Signature::LEN_ENCODED, 64);
450    }
451
452    fn test_hasher_multiple_runs<H: Hasher>() {
453        // Generate initial hash
454        let mut hasher = H::new();
455        hasher.update(b"hello world");
456        let digest = hasher.finalize();
457        assert!(H::Digest::try_from(digest.as_ref()).is_ok());
458        assert_eq!(digest.as_ref().len(), H::Digest::LEN_ENCODED);
459
460        // Reuse hasher without reset
461        hasher.update(b"hello world");
462        let digest_again = hasher.finalize();
463        assert!(H::Digest::try_from(digest_again.as_ref()).is_ok());
464        assert_eq!(digest, digest_again);
465
466        // Reuse hasher with reset
467        hasher.update(b"hello mars");
468        hasher.reset();
469        hasher.update(b"hello world");
470        let digest_reset = hasher.finalize();
471        assert!(H::Digest::try_from(digest_reset.as_ref()).is_ok());
472        assert_eq!(digest, digest_reset);
473
474        // Hash different data
475        hasher.update(b"hello mars");
476        let digest_mars = hasher.finalize();
477        assert!(H::Digest::try_from(digest_mars.as_ref()).is_ok());
478        assert_ne!(digest, digest_mars);
479    }
480
481    fn test_hasher_multiple_updates<H: Hasher>() {
482        // Generate initial hash
483        let mut hasher = H::new();
484        hasher.update(b"hello");
485        hasher.update(b" world");
486        let digest = hasher.finalize();
487        assert!(H::Digest::try_from(digest.as_ref()).is_ok());
488
489        // Generate hash in oneshot
490        let mut hasher = H::new();
491        hasher.update(b"hello world");
492        let digest_oneshot = hasher.finalize();
493        assert!(H::Digest::try_from(digest_oneshot.as_ref()).is_ok());
494        assert_eq!(digest, digest_oneshot);
495    }
496
497    fn test_hasher_empty_input<H: Hasher>() {
498        let mut hasher = H::new();
499        let digest = hasher.finalize();
500        assert!(H::Digest::try_from(digest.as_ref()).is_ok());
501    }
502
503    fn test_hasher_large_input<H: Hasher>() {
504        let mut hasher = H::new();
505        let data = vec![1; 1024];
506        hasher.update(&data);
507        let digest = hasher.finalize();
508        assert!(H::Digest::try_from(digest.as_ref()).is_ok());
509    }
510
511    #[test]
512    fn test_sha256_hasher_multiple_runs() {
513        test_hasher_multiple_runs::<Sha256>();
514    }
515
516    #[test]
517    fn test_sha256_hasher_multiple_updates() {
518        test_hasher_multiple_updates::<Sha256>();
519    }
520
521    #[test]
522    fn test_sha256_hasher_empty_input() {
523        test_hasher_empty_input::<Sha256>();
524    }
525
526    #[test]
527    fn test_sha256_hasher_large_input() {
528        test_hasher_large_input::<Sha256>();
529    }
530}