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