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