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