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