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: From<Self::PrivateKey> + 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 provided seed.
65    ///
66    /// # Warning
67    ///
68    /// This function is insecure and should only be used for examples
69    /// and testing.
70    fn from_seed(seed: u64) -> Self {
71        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
72        Self::new(&mut rng)
73    }
74
75    /// Returns the private key of the signer.
76    fn private_key(&self) -> Self::PrivateKey;
77
78    /// Returns the public key of the signer.
79    fn public_key(&self) -> Self::PublicKey;
80}
81
82/// Implementation that can both sign and verify messages.
83pub trait Scheme: Signer + Verifier {}
84
85/// Blanket implementation of the `Scheme` trait for types that implement both the `Signer` and `Verifier` traits.
86impl<T> Scheme for T where T: Signer + Verifier {}
87
88/// Implementation that can indicate whether all `Signatures` are correct or that some `Signature`
89/// is incorrect.
90pub trait BatchScheme: Specification {
91    /// Create a new batch scheme.
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    /// [union_unique](commonware_utils::union_unique) for details.
103    fn add(
104        &mut self,
105        namespace: Option<&[u8]>,
106        message: &[u8],
107        public_key: &Self::PublicKey,
108        signature: &Self::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<D: Digest>: Clone + Sized + Send + Sync + 'static {
141    /// Returns a unique representation of the object as a [Digest].
142    ///
143    /// If many objects with [Digest]s are related (map to some higher-level
144    /// group [Digest]), you should also implement [Committable].
145    fn digest(&self) -> D;
146}
147
148/// An object that shares a (commitment) [Digest] with other, related values.
149pub trait Committable<D: Digest>: Clone + Sized + Send + Sync + 'static {
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) -> D;
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: Scheme>() {
204        let signer = C::new(&mut OsRng);
205        let public_key = signer.public_key();
206        assert!(C::PublicKey::decode(public_key.as_ref()).is_ok());
207    }
208
209    fn test_from_valid_private_key<C: Scheme>() {
210        let signer = C::new(&mut OsRng);
211        let private_key = signer.private_key();
212        let public_key = signer.public_key();
213        let signer = C::from(private_key);
214        assert_eq!(public_key, signer.public_key());
215    }
216
217    fn test_validate_invalid_public_key<C: Signer>() {
218        let result = C::PublicKey::decode(vec![0; 1024].as_ref());
219        assert!(result.is_err());
220    }
221
222    fn test_sign_and_verify<C: Scheme>() {
223        let mut signer = C::from_seed(0);
224        let namespace = Some(&b"test_namespace"[..]);
225        let message = b"test_message";
226        let signature = signer.sign(namespace, message);
227        let public_key = signer.public_key();
228        assert!(C::verify(namespace, message, &public_key, &signature));
229    }
230
231    fn test_sign_and_verify_wrong_message<C: Scheme>() {
232        let mut signer = C::from_seed(0);
233        let namespace: Option<&[u8]> = Some(&b"test_namespace"[..]);
234        let message = b"test_message";
235        let wrong_message = b"wrong_message";
236        let signature = signer.sign(namespace, message);
237        let public_key = signer.public_key();
238        assert!(!C::verify(
239            namespace,
240            wrong_message,
241            &public_key,
242            &signature
243        ));
244    }
245
246    fn test_sign_and_verify_wrong_namespace<C: Scheme>() {
247        let mut signer = C::from_seed(0);
248        let namespace = Some(&b"test_namespace"[..]);
249        let wrong_namespace = Some(&b"wrong_namespace"[..]);
250        let message = b"test_message";
251        let signature = signer.sign(namespace, message);
252        let public_key = signer.public_key();
253        assert!(!C::verify(
254            wrong_namespace,
255            message,
256            &public_key,
257            &signature
258        ));
259    }
260
261    fn test_empty_vs_none_namespace<C: Scheme>() {
262        let mut signer = C::from_seed(0);
263        let empty_namespace = Some(&b""[..]);
264        let message = b"test_message";
265        let signature = signer.sign(empty_namespace, message);
266        let public_key = signer.public_key();
267        assert!(C::verify(empty_namespace, message, &public_key, &signature));
268        assert!(!C::verify(None, message, &public_key, &signature));
269    }
270
271    fn test_signature_determinism<C: Scheme>() {
272        let mut signer_1 = C::from_seed(0);
273        let mut signer_2 = C::from_seed(0);
274        let namespace = Some(&b"test_namespace"[..]);
275        let message = b"test_message";
276        let signature_1 = signer_1.sign(namespace, message);
277        let signature_2 = signer_2.sign(namespace, message);
278        assert_eq!(signer_1.public_key(), signer_2.public_key());
279        assert_eq!(signature_1, signature_2);
280    }
281
282    fn test_invalid_signature_publickey_pair<C: Scheme>() {
283        let mut signer = C::from_seed(0);
284        let signer_2 = C::from_seed(1);
285        let namespace = Some(&b"test_namespace"[..]);
286        let message = b"test_message";
287        let signature = signer.sign(namespace, message);
288        let public_key = signer_2.public_key();
289        assert!(!C::verify(namespace, message, &public_key, &signature));
290    }
291
292    #[test]
293    fn test_ed25519_validate() {
294        test_validate::<Ed25519>();
295    }
296
297    #[test]
298    fn test_ed25519_validate_invalid_public_key() {
299        test_validate_invalid_public_key::<Ed25519>();
300    }
301
302    #[test]
303    fn test_ed25519_from_valid_private_key() {
304        test_from_valid_private_key::<Ed25519>();
305    }
306
307    #[test]
308    fn test_ed25519_sign_and_verify() {
309        test_sign_and_verify::<Ed25519>();
310    }
311
312    #[test]
313    fn test_ed25519_sign_and_verify_wrong_message() {
314        test_sign_and_verify_wrong_message::<Ed25519>();
315    }
316
317    #[test]
318    fn test_ed25519_sign_and_verify_wrong_namespace() {
319        test_sign_and_verify_wrong_namespace::<Ed25519>();
320    }
321
322    #[test]
323    fn test_ed25519_empty_vs_none_namespace() {
324        test_empty_vs_none_namespace::<Ed25519>();
325    }
326
327    #[test]
328    fn test_ed25519_signature_determinism() {
329        test_signature_determinism::<Ed25519>();
330    }
331
332    #[test]
333    fn test_ed25519_invalid_signature_publickey_pair() {
334        test_invalid_signature_publickey_pair::<Ed25519>();
335    }
336
337    #[test]
338    fn test_ed25519_len() {
339        assert_eq!(<Ed25519 as Specification>::PublicKey::SIZE, 32);
340        assert_eq!(<Ed25519 as Specification>::Signature::SIZE, 64);
341    }
342
343    #[test]
344    fn test_bls12381_validate() {
345        test_validate::<Bls12381>();
346    }
347
348    #[test]
349    fn test_bls12381_validate_invalid_public_key() {
350        test_validate_invalid_public_key::<Bls12381>();
351    }
352
353    #[test]
354    fn test_bls12381_from_valid_private_key() {
355        test_from_valid_private_key::<Bls12381>();
356    }
357
358    #[test]
359    fn test_bls12381_sign_and_verify() {
360        test_sign_and_verify::<Bls12381>();
361    }
362
363    #[test]
364    fn test_bls12381_sign_and_verify_wrong_message() {
365        test_sign_and_verify_wrong_message::<Bls12381>();
366    }
367
368    #[test]
369    fn test_bls12381_sign_and_verify_wrong_namespace() {
370        test_sign_and_verify_wrong_namespace::<Bls12381>();
371    }
372
373    #[test]
374    fn test_bls12381_empty_vs_none_namespace() {
375        test_empty_vs_none_namespace::<Bls12381>();
376    }
377
378    #[test]
379    fn test_bls12381_signature_determinism() {
380        test_signature_determinism::<Bls12381>();
381    }
382
383    #[test]
384    fn test_bls12381_invalid_signature_publickey_pair() {
385        test_invalid_signature_publickey_pair::<Bls12381>();
386    }
387
388    #[test]
389    fn test_bls12381_len() {
390        assert_eq!(<Bls12381 as Specification>::PublicKey::SIZE, 48);
391        assert_eq!(<Bls12381 as Specification>::Signature::SIZE, 96);
392    }
393
394    #[test]
395    fn test_secp256r1_validate() {
396        test_validate::<Secp256r1>();
397    }
398
399    #[test]
400    fn test_secp256r1_validate_invalid_public_key() {
401        test_validate_invalid_public_key::<Secp256r1>();
402    }
403
404    #[test]
405    fn test_secp256r1_from_valid_private_key() {
406        test_from_valid_private_key::<Secp256r1>();
407    }
408
409    #[test]
410    fn test_secp256r1_sign_and_verify() {
411        test_sign_and_verify::<Secp256r1>();
412    }
413
414    #[test]
415    fn test_secp256r1_sign_and_verify_wrong_message() {
416        test_sign_and_verify_wrong_message::<Secp256r1>();
417    }
418
419    #[test]
420    fn test_secp256r1_sign_and_verify_wrong_namespace() {
421        test_sign_and_verify_wrong_namespace::<Secp256r1>();
422    }
423
424    #[test]
425    fn test_secp256r1_empty_vs_none_namespace() {
426        test_empty_vs_none_namespace::<Secp256r1>();
427    }
428
429    #[test]
430    fn test_secp256r1_signature_determinism() {
431        test_signature_determinism::<Secp256r1>();
432    }
433
434    #[test]
435    fn test_secp256r1_invalid_signature_publickey_pair() {
436        test_invalid_signature_publickey_pair::<Secp256r1>();
437    }
438
439    #[test]
440    fn test_secp256r1_len() {
441        assert_eq!(<Secp256r1 as Specification>::PublicKey::SIZE, 33);
442        assert_eq!(<Secp256r1 as Specification>::Signature::SIZE, 64);
443    }
444
445    fn test_hasher_multiple_runs<H: Hasher>() {
446        // Generate initial hash
447        let mut hasher = H::new();
448        hasher.update(b"hello world");
449        let digest = hasher.finalize();
450        assert!(H::Digest::decode(digest.as_ref()).is_ok());
451        assert_eq!(digest.as_ref().len(), H::Digest::SIZE);
452
453        // Reuse hasher without reset
454        hasher.update(b"hello world");
455        let digest_again = hasher.finalize();
456        assert!(H::Digest::decode(digest_again.as_ref()).is_ok());
457        assert_eq!(digest, digest_again);
458
459        // Reuse hasher with reset
460        hasher.update(b"hello mars");
461        hasher.reset();
462        hasher.update(b"hello world");
463        let digest_reset = hasher.finalize();
464        assert!(H::Digest::decode(digest_reset.as_ref()).is_ok());
465        assert_eq!(digest, digest_reset);
466
467        // Hash different data
468        hasher.update(b"hello mars");
469        let digest_mars = hasher.finalize();
470        assert!(H::Digest::decode(digest_mars.as_ref()).is_ok());
471        assert_ne!(digest, digest_mars);
472    }
473
474    fn test_hasher_multiple_updates<H: Hasher>() {
475        // Generate initial hash
476        let mut hasher = H::new();
477        hasher.update(b"hello");
478        hasher.update(b" world");
479        let digest = hasher.finalize();
480        assert!(H::Digest::decode(digest.as_ref()).is_ok());
481
482        // Generate hash in oneshot
483        let mut hasher = H::new();
484        hasher.update(b"hello world");
485        let digest_oneshot = hasher.finalize();
486        assert!(H::Digest::decode(digest_oneshot.as_ref()).is_ok());
487        assert_eq!(digest, digest_oneshot);
488    }
489
490    fn test_hasher_empty_input<H: Hasher>() {
491        let mut hasher = H::new();
492        let digest = hasher.finalize();
493        assert!(H::Digest::decode(digest.as_ref()).is_ok());
494    }
495
496    fn test_hasher_large_input<H: Hasher>() {
497        let mut hasher = H::new();
498        let data = vec![1; 1024];
499        hasher.update(&data);
500        let digest = hasher.finalize();
501        assert!(H::Digest::decode(digest.as_ref()).is_ok());
502    }
503
504    #[test]
505    fn test_sha256_hasher_multiple_runs() {
506        test_hasher_multiple_runs::<Sha256>();
507    }
508
509    #[test]
510    fn test_sha256_hasher_multiple_updates() {
511        test_hasher_multiple_updates::<Sha256>();
512    }
513
514    #[test]
515    fn test_sha256_hasher_empty_input() {
516        test_hasher_empty_input::<Sha256>();
517    }
518
519    #[test]
520    fn test_sha256_hasher_large_input() {
521        test_hasher_large_input::<Sha256>();
522    }
523}