Skip to main content

commonware_cryptography/
lib.rs

1//! Generate keys, sign arbitrary messages, and deterministically verify signatures.
2//!
3//! # Status
4//!
5//! Stability varies by primitive. See [README](https://github.com/commonwarexyz/monorepo#stability) for details.
6
7#![doc(
8    html_logo_url = "https://commonware.xyz/imgs/rustdoc_logo.svg",
9    html_favicon_url = "https://commonware.xyz/favicon.ico"
10)]
11#![cfg_attr(not(any(feature = "std", test)), no_std)]
12
13#[cfg(not(feature = "std"))]
14extern crate alloc;
15
16// Modules containing #[macro_export] macros must use verbose cfg.
17// See rust-lang/rust#52234: macro-expanded macro_export macros cannot be referenced by absolute paths.
18#[cfg(not(any(
19    commonware_stability_GAMMA,
20    commonware_stability_DELTA,
21    commonware_stability_EPSILON,
22    commonware_stability_RESERVED
23)))] // BETA
24pub mod bls12381;
25#[cfg(not(any(
26    commonware_stability_GAMMA,
27    commonware_stability_DELTA,
28    commonware_stability_EPSILON,
29    commonware_stability_RESERVED
30)))] // BETA
31pub mod ed25519;
32#[cfg(not(any(
33    commonware_stability_BETA,
34    commonware_stability_GAMMA,
35    commonware_stability_DELTA,
36    commonware_stability_EPSILON,
37    commonware_stability_RESERVED
38)))] // ALPHA
39pub mod secp256r1;
40
41commonware_macros::stability_scope!(ALPHA {
42    pub mod bloomfilter;
43    pub use crate::bloomfilter::BloomFilter;
44
45    pub mod lthash;
46    pub use crate::lthash::LtHash;
47
48    pub mod zk;
49});
50commonware_macros::stability_scope!(BETA {
51    use commonware_codec::{Encode, ReadExt};
52    use commonware_math::algebra::Random;
53    use commonware_parallel::Strategy;
54    use commonware_utils::Array;
55    use rand::SeedableRng as _;
56    use rand_chacha::ChaCha20Rng;
57    use rand_core::CryptoRngCore;
58
59    pub mod secret;
60    pub use crate::secret::Secret;
61
62    pub mod certificate;
63    pub mod transcript;
64
65    pub mod sha256;
66    pub use crate::sha256::{CoreSha256, Sha256};
67    pub mod blake3;
68    pub use crate::blake3::{Blake3, CoreBlake3};
69    #[cfg(feature = "std")]
70    pub mod crc32;
71    #[cfg(feature = "std")]
72    pub use crate::crc32::Crc32;
73
74    #[cfg(feature = "std")]
75    pub mod handshake;
76
77    /// Produces [Signature]s over messages that can be verified with a corresponding [PublicKey].
78    pub trait Signer: Random + Send + Sync + Clone + 'static {
79        /// The type of [Signature] produced by this [Signer].
80        type Signature: Signature;
81
82        /// The corresponding [PublicKey] type.
83        type PublicKey: PublicKey<Signature = Self::Signature>;
84
85        /// Returns the [PublicKey] corresponding to this [Signer].
86        fn public_key(&self) -> Self::PublicKey;
87
88        /// Sign a message with the given namespace.
89        ///
90        /// The message should not be hashed prior to calling this function. If a particular scheme
91        /// requires a payload to be hashed before it is signed, it will be done internally.
92        ///
93        /// A namespace must be used to prevent cross-domain attacks (where a signature can be reused
94        /// in a different context). It must be prepended to the message so that a signature meant for
95        /// one context cannot be used unexpectedly in another (i.e. signing a message on the network
96        /// layer can't accidentally spend funds on the execution layer). See
97        /// [commonware_utils::union_unique] for details.
98        fn sign(&self, namespace: &[u8], msg: &[u8]) -> Self::Signature;
99
100        /// Create a [Signer] from a seed.
101        ///
102        /// # Warning
103        ///
104        /// This function is insecure and should only be used for examples
105        /// and testing.
106        fn from_seed(seed: u64) -> Self {
107            Self::random(&mut ChaCha20Rng::seed_from_u64(seed))
108        }
109    }
110
111    /// A [Signer] that can be serialized/deserialized.
112    pub trait PrivateKey: Signer + Sized + ReadExt + Encode {}
113
114    /// Verifies [Signature]s over messages.
115    pub trait Verifier {
116        /// The type of [Signature] that this verifier can verify.
117        type Signature: Signature;
118
119        /// Verify that a [Signature] is a valid over a given message.
120        ///
121        /// The message should not be hashed prior to calling this function. If a particular
122        /// scheme requires a payload to be hashed before it is signed, it will be done internally.
123        ///
124        /// Because namespace is prepended to message before signing, the namespace provided here must
125        /// match the namespace provided during signing.
126        fn verify(&self, namespace: &[u8], msg: &[u8], sig: &Self::Signature) -> bool;
127    }
128
129    /// A [PublicKey], able to verify [Signature]s.
130    pub trait PublicKey: Verifier + Sized + ReadExt + Encode + PartialEq + Array {}
131
132    /// A [Signature] over a message.
133    pub trait Signature: Sized + Clone + ReadExt + Encode + PartialEq + Array {}
134
135    /// An extension of [Signature] that supports public key recovery.
136    pub trait Recoverable: Signature {
137        /// The type of [PublicKey] that can be recovered from this [Signature].
138        type PublicKey: PublicKey<Signature = Self>;
139
140        /// Recover the [PublicKey] of the signer that created this [Signature] over the given message.
141        ///
142        /// The message should not be hashed prior to calling this function. If a particular
143        /// scheme requires a payload to be hashed before it is signed, it will be done internally.
144        ///
145        /// Like when verifying a signature, the namespace must match what was used during signing exactly.
146        fn recover_signer(&self, namespace: &[u8], msg: &[u8]) -> Option<Self::PublicKey>;
147    }
148
149    /// Verifies whether all [Signature]s are correct or that some [Signature] is incorrect.
150    pub trait BatchVerifier {
151        /// The type of public keys that this verifier can accept.
152        type PublicKey: PublicKey;
153
154        /// Create a new batch verifier.
155        fn new() -> Self;
156
157        /// Append item to the batch.
158        ///
159        /// The message should not be hashed prior to calling this function. If a particular scheme
160        /// requires a payload to be hashed before it is signed, it will be done internally.
161        ///
162        /// A namespace must be used to prevent replay attacks. It will be prepended to the message so
163        /// that a signature meant for one context cannot be used unexpectedly in another (i.e. signing
164        /// a message on the network layer can't accidentally spend funds on the execution layer). See
165        /// [commonware_utils::union_unique] for details.
166        fn add(
167            &mut self,
168            namespace: &[u8],
169            message: &[u8],
170            public_key: &Self::PublicKey,
171            signature: &<Self::PublicKey as Verifier>::Signature,
172        ) -> bool;
173
174        /// Verify all items added to the batch.
175        ///
176        /// Returns `true` if all items are valid, `false` otherwise.
177        ///
178        /// # Why Randomness?
179        ///
180        /// When performing batch verification, it is often important to add some randomness
181        /// to prevent an attacker from constructing a malicious batch of signatures that pass
182        /// batch verification but are invalid individually. Abstractly, think of this as
183        /// there existing two valid signatures (`c_1` and `c_2`) and an attacker proposing
184        /// (`c_1 + d` and `c_2 - d`).
185        ///
186        /// You can read more about this [here](https://ethresear.ch/t/security-of-bls-batch-verification/10748#the-importance-of-randomness-4).
187        fn verify<R: CryptoRngCore>(self, rng: &mut R, strategy: &impl Strategy) -> bool;
188    }
189
190    /// Specializes the [commonware_utils::Array] trait with the Copy trait for cryptographic digests
191    /// (which should be cheap to clone).
192    ///
193    /// # Warning
194    ///
195    /// This trait requires [`Random::random`], but generating a digest at random is
196    /// typically reserved for testing, and not production use.
197    pub trait Digest: Array + Copy + Random {
198        /// An empty (all-zero) digest.
199        const EMPTY: Self;
200    }
201
202    /// An object that can be uniquely represented as a [Digest].
203    pub trait Digestible: Clone + Sized + Send + Sync + 'static {
204        /// The type of digest produced by this object.
205        type Digest: Digest;
206
207        /// Returns a unique representation of the object as a [Digest].
208        ///
209        /// If many objects with [Digest]s are related (map to some higher-level
210        /// group [Digest]), you should also implement [Committable].
211        fn digest(&self) -> Self::Digest;
212    }
213
214    /// An object that can produce a commitment of itself.
215    pub trait Committable: Clone + Sized + Send + Sync + 'static {
216        /// The type of commitment produced by this object.
217        type Commitment: Digest;
218
219        /// Returns the unique commitment of the object as a [Digest].
220        ///
221        /// For simple objects (like a block), this is often just the digest of the object
222        /// itself. For more complex objects, however, this may represent some root or base
223        /// of a proof structure (where many unique objects map to the same commitment).
224        ///
225        /// # Warning
226        ///
227        /// It must not be possible for two objects with the same [Digest] to map
228        /// to different commitments. Primitives assume there is a one-to-one
229        /// relation between digest and commitment and a one-to-many relation
230        /// between commitment and digest.
231        fn commitment(&self) -> Self::Commitment;
232    }
233
234    pub type DigestOf<H> = <H as Hasher>::Digest;
235
236    /// Interface that commonware crates rely on for hashing.
237    ///
238    /// Hash functions in commonware primitives are not typically hardcoded
239    /// to a specific algorithm (e.g. SHA-256) because different hash functions
240    /// may work better with different cryptographic schemes, may be more efficient
241    /// to use in STARK/SNARK proofs, or provide different levels of security (with some
242    /// performance/size penalty).
243    ///
244    /// This trait is required to implement the `Clone` trait because it is often
245    /// part of a struct that is cloned. In practice, implementations do not actually
246    /// clone the hasher state but users should not rely on this behavior and call `reset`
247    /// after cloning.
248    pub trait Hasher: Default + Clone + Send + Sync + 'static {
249        /// Digest generated by the hasher.
250        type Digest: Digest;
251
252        /// Create a new, empty hasher.
253        fn new() -> Self {
254            Self::default()
255        }
256
257        /// Append message to previously recorded data.
258        fn update(&mut self, message: &[u8]) -> &mut Self;
259
260        /// Hash all recorded data and reset the hasher
261        /// to the initial state.
262        fn finalize(&mut self) -> Self::Digest;
263
264        /// Reset the hasher without generating a hash.
265        ///
266        /// This function does not need to be called after `finalize`.
267        fn reset(&mut self) -> &mut Self;
268
269        /// Hash a single message with a one-time-use hasher.
270        fn hash(message: &[u8]) -> Self::Digest {
271            Self::new().update(message).finalize()
272        }
273    }
274});
275
276#[cfg(test)]
277mod tests {
278    use super::*;
279    use commonware_codec::{DecodeExt, FixedSize};
280    use commonware_utils::test_rng;
281
282    fn test_validate<C: PrivateKey>() {
283        let private_key = C::random(&mut test_rng());
284        let public_key = private_key.public_key();
285        assert!(C::PublicKey::decode(public_key.as_ref()).is_ok());
286    }
287
288    fn test_validate_invalid_public_key<C: Signer>() {
289        let result = C::PublicKey::decode(vec![0; 1024].as_ref());
290        assert!(result.is_err());
291    }
292
293    fn test_sign_and_verify<C: PrivateKey>() {
294        let private_key = C::from_seed(0);
295        let namespace = b"test_namespace";
296        let message = b"test_message";
297        let signature = private_key.sign(namespace, message);
298        let public_key = private_key.public_key();
299        assert!(public_key.verify(namespace, message, &signature));
300    }
301
302    fn test_sign_and_verify_wrong_message<C: PrivateKey>() {
303        let private_key = C::from_seed(0);
304        let namespace = b"test_namespace";
305        let message = b"test_message";
306        let wrong_message = b"wrong_message";
307        let signature = private_key.sign(namespace, message);
308        let public_key = private_key.public_key();
309        assert!(!public_key.verify(namespace, wrong_message, &signature));
310    }
311
312    fn test_sign_and_verify_wrong_namespace<C: PrivateKey>() {
313        let private_key = C::from_seed(0);
314        let namespace = b"test_namespace";
315        let wrong_namespace = b"wrong_namespace";
316        let message = b"test_message";
317        let signature = private_key.sign(namespace, message);
318        let public_key = private_key.public_key();
319        assert!(!public_key.verify(wrong_namespace, message, &signature));
320    }
321
322    fn test_empty_namespace<C: PrivateKey>() {
323        let private_key = C::from_seed(0);
324        let empty_namespace = b"";
325        let message = b"test_message";
326        let signature = private_key.sign(empty_namespace, message);
327        let public_key = private_key.public_key();
328        assert!(public_key.verify(empty_namespace, message, &signature));
329    }
330
331    fn test_signature_determinism<C: PrivateKey>() {
332        let private_key_1 = C::from_seed(0);
333        let private_key_2 = C::from_seed(0);
334        let namespace = b"test_namespace";
335        let message = b"test_message";
336        let signature_1 = private_key_1.sign(namespace, message);
337        let signature_2 = private_key_2.sign(namespace, message);
338        assert_eq!(private_key_1.public_key(), private_key_2.public_key());
339        assert_eq!(signature_1, signature_2);
340    }
341
342    fn test_invalid_signature_publickey_pair<C: PrivateKey>() {
343        let private_key = C::from_seed(0);
344        let private_key_2 = C::from_seed(1);
345        let namespace = b"test_namespace";
346        let message = b"test_message";
347        let signature = private_key.sign(namespace, message);
348        let public_key = private_key_2.public_key();
349        assert!(!public_key.verify(namespace, message, &signature));
350    }
351
352    #[test]
353    fn test_ed25519_validate() {
354        test_validate::<ed25519::PrivateKey>();
355    }
356
357    #[test]
358    fn test_ed25519_validate_invalid_public_key() {
359        test_validate_invalid_public_key::<ed25519::PrivateKey>();
360    }
361
362    #[test]
363    fn test_ed25519_sign_and_verify() {
364        test_sign_and_verify::<ed25519::PrivateKey>();
365    }
366
367    #[test]
368    fn test_ed25519_sign_and_verify_wrong_message() {
369        test_sign_and_verify_wrong_message::<ed25519::PrivateKey>();
370    }
371
372    #[test]
373    fn test_ed25519_sign_and_verify_wrong_namespace() {
374        test_sign_and_verify_wrong_namespace::<ed25519::PrivateKey>();
375    }
376
377    #[test]
378    fn test_ed25519_empty_namespace() {
379        test_empty_namespace::<ed25519::PrivateKey>();
380    }
381
382    #[test]
383    fn test_ed25519_signature_determinism() {
384        test_signature_determinism::<ed25519::PrivateKey>();
385    }
386
387    #[test]
388    fn test_ed25519_invalid_signature_publickey_pair() {
389        test_invalid_signature_publickey_pair::<ed25519::PrivateKey>();
390    }
391
392    #[test]
393    fn test_ed25519_len() {
394        assert_eq!(ed25519::PublicKey::SIZE, 32);
395        assert_eq!(ed25519::Signature::SIZE, 64);
396    }
397
398    #[test]
399    fn test_bls12381_validate() {
400        test_validate::<bls12381::PrivateKey>();
401    }
402
403    #[test]
404    fn test_bls12381_validate_invalid_public_key() {
405        test_validate_invalid_public_key::<bls12381::PrivateKey>();
406    }
407
408    #[test]
409    fn test_bls12381_sign_and_verify() {
410        test_sign_and_verify::<bls12381::PrivateKey>();
411    }
412
413    #[test]
414    fn test_bls12381_sign_and_verify_wrong_message() {
415        test_sign_and_verify_wrong_message::<bls12381::PrivateKey>();
416    }
417
418    #[test]
419    fn test_bls12381_sign_and_verify_wrong_namespace() {
420        test_sign_and_verify_wrong_namespace::<bls12381::PrivateKey>();
421    }
422
423    #[test]
424    fn test_bls12381_empty_namespace() {
425        test_empty_namespace::<bls12381::PrivateKey>();
426    }
427
428    #[test]
429    fn test_bls12381_signature_determinism() {
430        test_signature_determinism::<bls12381::PrivateKey>();
431    }
432
433    #[test]
434    fn test_bls12381_invalid_signature_publickey_pair() {
435        test_invalid_signature_publickey_pair::<bls12381::PrivateKey>();
436    }
437
438    #[test]
439    fn test_bls12381_len() {
440        assert_eq!(bls12381::PublicKey::SIZE, 48);
441        assert_eq!(bls12381::Signature::SIZE, 96);
442    }
443
444    #[test]
445    fn test_secp256r1_standard_validate() {
446        test_validate::<secp256r1::standard::PrivateKey>();
447    }
448
449    #[test]
450    fn test_secp256r1_standard_validate_invalid_public_key() {
451        test_validate_invalid_public_key::<secp256r1::standard::PrivateKey>();
452    }
453
454    #[test]
455    fn test_secp256r1_standard_sign_and_verify() {
456        test_sign_and_verify::<secp256r1::standard::PrivateKey>();
457    }
458
459    #[test]
460    fn test_secp256r1_standard_sign_and_verify_wrong_message() {
461        test_sign_and_verify_wrong_message::<secp256r1::standard::PrivateKey>();
462    }
463
464    #[test]
465    fn test_secp256r1_standard_sign_and_verify_wrong_namespace() {
466        test_sign_and_verify_wrong_namespace::<secp256r1::standard::PrivateKey>();
467    }
468
469    #[test]
470    fn test_secp256r1_standard_empty_namespace() {
471        test_empty_namespace::<secp256r1::standard::PrivateKey>();
472    }
473
474    #[test]
475    fn test_secp256r1_standard_signature_determinism() {
476        test_signature_determinism::<secp256r1::standard::PrivateKey>();
477    }
478
479    #[test]
480    fn test_secp256r1_standard_invalid_signature_publickey_pair() {
481        test_invalid_signature_publickey_pair::<secp256r1::standard::PrivateKey>();
482    }
483
484    #[test]
485    fn test_secp256r1_standard_len() {
486        assert_eq!(secp256r1::standard::PublicKey::SIZE, 33);
487        assert_eq!(secp256r1::standard::Signature::SIZE, 64);
488    }
489
490    #[test]
491    fn test_secp256r1_recoverable_validate() {
492        test_validate::<secp256r1::recoverable::PrivateKey>();
493    }
494
495    #[test]
496    fn test_secp256r1_recoverable_validate_invalid_public_key() {
497        test_validate_invalid_public_key::<secp256r1::recoverable::PrivateKey>();
498    }
499
500    #[test]
501    fn test_secp256r1_recoverable_sign_and_verify() {
502        test_sign_and_verify::<secp256r1::recoverable::PrivateKey>();
503    }
504
505    #[test]
506    fn test_secp256r1_recoverable_sign_and_verify_wrong_message() {
507        test_sign_and_verify_wrong_message::<secp256r1::recoverable::PrivateKey>();
508    }
509
510    #[test]
511    fn test_secp256r1_recoverable_sign_and_verify_wrong_namespace() {
512        test_sign_and_verify_wrong_namespace::<secp256r1::recoverable::PrivateKey>();
513    }
514
515    #[test]
516    fn test_secp256r1_recoverable_empty_namespace() {
517        test_empty_namespace::<secp256r1::recoverable::PrivateKey>();
518    }
519
520    #[test]
521    fn test_secp256r1_recoverable_signature_determinism() {
522        test_signature_determinism::<secp256r1::recoverable::PrivateKey>();
523    }
524
525    #[test]
526    fn test_secp256r1_recoverable_invalid_signature_publickey_pair() {
527        test_invalid_signature_publickey_pair::<secp256r1::recoverable::PrivateKey>();
528    }
529
530    #[test]
531    fn test_secp256r1_recoverable_len() {
532        assert_eq!(secp256r1::recoverable::PublicKey::SIZE, 33);
533        assert_eq!(secp256r1::recoverable::Signature::SIZE, 65);
534    }
535
536    fn test_hasher_multiple_runs<H: Hasher>() {
537        // Generate initial hash
538        let mut hasher = H::new();
539        hasher.update(b"hello world");
540        let digest = hasher.finalize();
541        assert!(H::Digest::decode(digest.as_ref()).is_ok());
542        assert_eq!(digest.as_ref().len(), H::Digest::SIZE);
543
544        // Reuse hasher without reset
545        hasher.update(b"hello world");
546        let digest_again = hasher.finalize();
547        assert!(H::Digest::decode(digest_again.as_ref()).is_ok());
548        assert_eq!(digest, digest_again);
549
550        // Reuse hasher with reset
551        hasher.update(b"hello mars");
552        hasher.reset();
553        hasher.update(b"hello world");
554        let digest_reset = hasher.finalize();
555        assert!(H::Digest::decode(digest_reset.as_ref()).is_ok());
556        assert_eq!(digest, digest_reset);
557
558        // Hash different data
559        hasher.update(b"hello mars");
560        let digest_mars = hasher.finalize();
561        assert!(H::Digest::decode(digest_mars.as_ref()).is_ok());
562        assert_ne!(digest, digest_mars);
563    }
564
565    fn test_hasher_multiple_updates<H: Hasher>() {
566        // Generate initial hash
567        let mut hasher = H::new();
568        hasher.update(b"hello");
569        hasher.update(b" world");
570        let digest = hasher.finalize();
571        assert!(H::Digest::decode(digest.as_ref()).is_ok());
572
573        // Generate hash in oneshot
574        let mut hasher = H::new();
575        hasher.update(b"hello world");
576        let digest_oneshot = hasher.finalize();
577        assert!(H::Digest::decode(digest_oneshot.as_ref()).is_ok());
578        assert_eq!(digest, digest_oneshot);
579    }
580
581    fn test_hasher_empty_input<H: Hasher>() {
582        let mut hasher = H::new();
583        let digest = hasher.finalize();
584        assert!(H::Digest::decode(digest.as_ref()).is_ok());
585    }
586
587    fn test_hasher_large_input<H: Hasher>() {
588        let mut hasher = H::new();
589        let data = vec![1; 1024];
590        hasher.update(&data);
591        let digest = hasher.finalize();
592        assert!(H::Digest::decode(digest.as_ref()).is_ok());
593    }
594
595    #[test]
596    fn test_sha256_hasher_multiple_runs() {
597        test_hasher_multiple_runs::<Sha256>();
598    }
599
600    #[test]
601    fn test_sha256_hasher_multiple_updates() {
602        test_hasher_multiple_updates::<Sha256>();
603    }
604
605    #[test]
606    fn test_sha256_hasher_empty_input() {
607        test_hasher_empty_input::<Sha256>();
608    }
609
610    #[test]
611    fn test_sha256_hasher_large_input() {
612        test_hasher_large_input::<Sha256>();
613    }
614}