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 generate a digest.
135pub trait Digestible<D: Digest>: Clone + Send + Sync + 'static {
136    /// Generate a digest from the object.
137    fn digest(&self) -> D;
138}
139
140/// Interface that commonware crates rely on for hashing.
141///
142/// Hash functions in commonware primitives are not typically hardcoded
143/// to a specific algorithm (e.g. SHA-256) because different hash functions
144/// may work better with different cryptographic schemes, may be more efficient
145/// to use in STARK/SNARK proofs, or provide different levels of security (with some
146/// performance/size penalty).
147///
148/// This trait is required to implement the `Clone` trait because it is often
149/// part of a struct that is cloned. In practice, implementations do not actually
150/// clone the hasher state but users should not rely on this behavior and call `reset`
151/// after cloning.
152pub trait Hasher: Clone + Send + Sync + 'static {
153    /// Digest generated by the hasher.
154    type Digest: Digest;
155
156    /// Create a new hasher.
157    fn new() -> Self;
158
159    /// Append message to previously recorded data.
160    fn update(&mut self, message: &[u8]);
161
162    /// Hash all recorded data and reset the hasher
163    /// to the initial state.
164    fn finalize(&mut self) -> Self::Digest;
165
166    /// Reset the hasher without generating a hash.
167    ///
168    /// This function does not need to be called after `finalize`.
169    fn reset(&mut self);
170
171    /// Generate a random digest.
172    ///
173    /// # Warning
174    ///
175    /// This function is typically used for testing and is not recommended
176    /// for production use.
177    fn random<R: Rng + CryptoRng>(rng: &mut R) -> Self::Digest;
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183    use commonware_codec::{DecodeExt, FixedSize};
184    use rand::rngs::OsRng;
185
186    fn test_validate<C: Scheme>() {
187        let signer = C::new(&mut OsRng);
188        let public_key = signer.public_key();
189        assert!(C::PublicKey::decode(public_key.as_ref()).is_ok());
190    }
191
192    fn test_from_valid_private_key<C: Scheme>() {
193        let signer = C::new(&mut OsRng);
194        let private_key = signer.private_key();
195        let public_key = signer.public_key();
196        let signer = C::from(private_key).unwrap();
197        assert_eq!(public_key, signer.public_key());
198    }
199
200    fn test_validate_invalid_public_key<C: Signer>() {
201        let result = C::PublicKey::decode(vec![0; 1024].as_ref());
202        assert!(result.is_err());
203    }
204
205    fn test_sign_and_verify<C: Scheme>() {
206        let mut signer = C::from_seed(0);
207        let namespace = Some(&b"test_namespace"[..]);
208        let message = b"test_message";
209        let signature = signer.sign(namespace, message);
210        let public_key = signer.public_key();
211        assert!(C::verify(namespace, message, &public_key, &signature));
212    }
213
214    fn test_sign_and_verify_wrong_message<C: Scheme>() {
215        let mut signer = C::from_seed(0);
216        let namespace: Option<&[u8]> = Some(&b"test_namespace"[..]);
217        let message = b"test_message";
218        let wrong_message = b"wrong_message";
219        let signature = signer.sign(namespace, message);
220        let public_key = signer.public_key();
221        assert!(!C::verify(
222            namespace,
223            wrong_message,
224            &public_key,
225            &signature
226        ));
227    }
228
229    fn test_sign_and_verify_wrong_namespace<C: Scheme>() {
230        let mut signer = C::from_seed(0);
231        let namespace = Some(&b"test_namespace"[..]);
232        let wrong_namespace = Some(&b"wrong_namespace"[..]);
233        let message = b"test_message";
234        let signature = signer.sign(namespace, message);
235        let public_key = signer.public_key();
236        assert!(!C::verify(
237            wrong_namespace,
238            message,
239            &public_key,
240            &signature
241        ));
242    }
243
244    fn test_empty_vs_none_namespace<C: Scheme>() {
245        let mut signer = C::from_seed(0);
246        let empty_namespace = Some(&b""[..]);
247        let message = b"test_message";
248        let signature = signer.sign(empty_namespace, message);
249        let public_key = signer.public_key();
250        assert!(C::verify(empty_namespace, message, &public_key, &signature));
251        assert!(!C::verify(None, message, &public_key, &signature));
252    }
253
254    fn test_signature_determinism<C: Scheme>() {
255        let mut signer_1 = C::from_seed(0);
256        let mut signer_2 = C::from_seed(0);
257        let namespace = Some(&b"test_namespace"[..]);
258        let message = b"test_message";
259        let signature_1 = signer_1.sign(namespace, message);
260        let signature_2 = signer_2.sign(namespace, message);
261        assert_eq!(signer_1.public_key(), signer_2.public_key());
262        assert_eq!(signature_1, signature_2);
263    }
264
265    fn test_invalid_signature_publickey_pair<C: Scheme>() {
266        let mut signer = C::from_seed(0);
267        let signer_2 = C::from_seed(1);
268        let namespace = Some(&b"test_namespace"[..]);
269        let message = b"test_message";
270        let signature = signer.sign(namespace, message);
271        let public_key = signer_2.public_key();
272        assert!(!C::verify(namespace, message, &public_key, &signature));
273    }
274
275    #[test]
276    fn test_ed25519_validate() {
277        test_validate::<Ed25519>();
278    }
279
280    #[test]
281    fn test_ed25519_validate_invalid_public_key() {
282        test_validate_invalid_public_key::<Ed25519>();
283    }
284
285    #[test]
286    fn test_ed25519_from_valid_private_key() {
287        test_from_valid_private_key::<Ed25519>();
288    }
289
290    #[test]
291    fn test_ed25519_sign_and_verify() {
292        test_sign_and_verify::<Ed25519>();
293    }
294
295    #[test]
296    fn test_ed25519_sign_and_verify_wrong_message() {
297        test_sign_and_verify_wrong_message::<Ed25519>();
298    }
299
300    #[test]
301    fn test_ed25519_sign_and_verify_wrong_namespace() {
302        test_sign_and_verify_wrong_namespace::<Ed25519>();
303    }
304
305    #[test]
306    fn test_ed25519_empty_vs_none_namespace() {
307        test_empty_vs_none_namespace::<Ed25519>();
308    }
309
310    #[test]
311    fn test_ed25519_signature_determinism() {
312        test_signature_determinism::<Ed25519>();
313    }
314
315    #[test]
316    fn test_ed25519_invalid_signature_publickey_pair() {
317        test_invalid_signature_publickey_pair::<Ed25519>();
318    }
319
320    #[test]
321    fn test_ed25519_len() {
322        assert_eq!(<Ed25519 as Specification>::PublicKey::SIZE, 32);
323        assert_eq!(<Ed25519 as Specification>::Signature::SIZE, 64);
324    }
325
326    #[test]
327    fn test_bls12381_validate() {
328        test_validate::<Bls12381>();
329    }
330
331    #[test]
332    fn test_bls12381_validate_invalid_public_key() {
333        test_validate_invalid_public_key::<Bls12381>();
334    }
335
336    #[test]
337    fn test_bls12381_from_valid_private_key() {
338        test_from_valid_private_key::<Bls12381>();
339    }
340
341    #[test]
342    fn test_bls12381_sign_and_verify() {
343        test_sign_and_verify::<Bls12381>();
344    }
345
346    #[test]
347    fn test_bls12381_sign_and_verify_wrong_message() {
348        test_sign_and_verify_wrong_message::<Bls12381>();
349    }
350
351    #[test]
352    fn test_bls12381_sign_and_verify_wrong_namespace() {
353        test_sign_and_verify_wrong_namespace::<Bls12381>();
354    }
355
356    #[test]
357    fn test_bls12381_empty_vs_none_namespace() {
358        test_empty_vs_none_namespace::<Bls12381>();
359    }
360
361    #[test]
362    fn test_bls12381_signature_determinism() {
363        test_signature_determinism::<Bls12381>();
364    }
365
366    #[test]
367    fn test_bls12381_invalid_signature_publickey_pair() {
368        test_invalid_signature_publickey_pair::<Bls12381>();
369    }
370
371    #[test]
372    fn test_bls12381_len() {
373        assert_eq!(<Bls12381 as Specification>::PublicKey::SIZE, 48);
374        assert_eq!(<Bls12381 as Specification>::Signature::SIZE, 96);
375    }
376
377    #[test]
378    fn test_secp256r1_validate() {
379        test_validate::<Secp256r1>();
380    }
381
382    #[test]
383    fn test_secp256r1_validate_invalid_public_key() {
384        test_validate_invalid_public_key::<Secp256r1>();
385    }
386
387    #[test]
388    fn test_secp256r1_from_valid_private_key() {
389        test_from_valid_private_key::<Secp256r1>();
390    }
391
392    #[test]
393    fn test_secp256r1_sign_and_verify() {
394        test_sign_and_verify::<Secp256r1>();
395    }
396
397    #[test]
398    fn test_secp256r1_sign_and_verify_wrong_message() {
399        test_sign_and_verify_wrong_message::<Secp256r1>();
400    }
401
402    #[test]
403    fn test_secp256r1_sign_and_verify_wrong_namespace() {
404        test_sign_and_verify_wrong_namespace::<Secp256r1>();
405    }
406
407    #[test]
408    fn test_secp256r1_empty_vs_none_namespace() {
409        test_empty_vs_none_namespace::<Secp256r1>();
410    }
411
412    #[test]
413    fn test_secp256r1_signature_determinism() {
414        test_signature_determinism::<Secp256r1>();
415    }
416
417    #[test]
418    fn test_secp256r1_invalid_signature_publickey_pair() {
419        test_invalid_signature_publickey_pair::<Secp256r1>();
420    }
421
422    #[test]
423    fn test_secp256r1_len() {
424        assert_eq!(<Secp256r1 as Specification>::PublicKey::SIZE, 33);
425        assert_eq!(<Secp256r1 as Specification>::Signature::SIZE, 64);
426    }
427
428    fn test_hasher_multiple_runs<H: Hasher>() {
429        // Generate initial hash
430        let mut hasher = H::new();
431        hasher.update(b"hello world");
432        let digest = hasher.finalize();
433        assert!(H::Digest::decode(digest.as_ref()).is_ok());
434        assert_eq!(digest.as_ref().len(), H::Digest::SIZE);
435
436        // Reuse hasher without reset
437        hasher.update(b"hello world");
438        let digest_again = hasher.finalize();
439        assert!(H::Digest::decode(digest_again.as_ref()).is_ok());
440        assert_eq!(digest, digest_again);
441
442        // Reuse hasher with reset
443        hasher.update(b"hello mars");
444        hasher.reset();
445        hasher.update(b"hello world");
446        let digest_reset = hasher.finalize();
447        assert!(H::Digest::decode(digest_reset.as_ref()).is_ok());
448        assert_eq!(digest, digest_reset);
449
450        // Hash different data
451        hasher.update(b"hello mars");
452        let digest_mars = hasher.finalize();
453        assert!(H::Digest::decode(digest_mars.as_ref()).is_ok());
454        assert_ne!(digest, digest_mars);
455    }
456
457    fn test_hasher_multiple_updates<H: Hasher>() {
458        // Generate initial hash
459        let mut hasher = H::new();
460        hasher.update(b"hello");
461        hasher.update(b" world");
462        let digest = hasher.finalize();
463        assert!(H::Digest::decode(digest.as_ref()).is_ok());
464
465        // Generate hash in oneshot
466        let mut hasher = H::new();
467        hasher.update(b"hello world");
468        let digest_oneshot = hasher.finalize();
469        assert!(H::Digest::decode(digest_oneshot.as_ref()).is_ok());
470        assert_eq!(digest, digest_oneshot);
471    }
472
473    fn test_hasher_empty_input<H: Hasher>() {
474        let mut hasher = H::new();
475        let digest = hasher.finalize();
476        assert!(H::Digest::decode(digest.as_ref()).is_ok());
477    }
478
479    fn test_hasher_large_input<H: Hasher>() {
480        let mut hasher = H::new();
481        let data = vec![1; 1024];
482        hasher.update(&data);
483        let digest = hasher.finalize();
484        assert!(H::Digest::decode(digest.as_ref()).is_ok());
485    }
486
487    #[test]
488    fn test_sha256_hasher_multiple_runs() {
489        test_hasher_multiple_runs::<Sha256>();
490    }
491
492    #[test]
493    fn test_sha256_hasher_multiple_updates() {
494        test_hasher_multiple_updates::<Sha256>();
495    }
496
497    #[test]
498    fn test_sha256_hasher_empty_input() {
499        test_hasher_empty_input::<Sha256>();
500    }
501
502    #[test]
503    fn test_sha256_hasher_large_input() {
504        test_hasher_large_input::<Sha256>();
505    }
506}