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