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