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