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