Skip to main content

commonware_cryptography/
lib.rs

1//! Generate keys, sign arbitrary messages, and deterministically verify signatures.
2//!
3//! # Randomness
4//!
5//! Cryptographic operations that accept an RNG require a cryptographically secure and
6//! unpredictable source unless documented otherwise. A weak or predictable RNG may compromise
7//! security.
8//!
9//! # Status
10//!
11//! Stability varies by primitive. See [README](https://github.com/commonwarexyz/monorepo#stability) for details.
12
13#![doc(
14    html_logo_url = "https://commonware.xyz/imgs/rustdoc_logo.svg",
15    html_favicon_url = "https://commonware.xyz/favicon.ico"
16)]
17#![cfg_attr(not(any(feature = "std", test)), no_std)]
18
19#[cfg(not(feature = "std"))]
20extern crate alloc;
21
22// Modules containing #[macro_export] macros must use verbose cfg.
23// See rust-lang/rust#52234: macro-expanded macro_export macros cannot be referenced by absolute paths.
24#[cfg(all(
25    feature = "bls12381",
26    not(any(
27        commonware_stability_GAMMA,
28        commonware_stability_DELTA,
29        commonware_stability_EPSILON,
30        commonware_stability_RESERVED
31    ))
32))] // BETA
33pub mod bls12381;
34#[cfg(not(any(
35    commonware_stability_GAMMA,
36    commonware_stability_DELTA,
37    commonware_stability_EPSILON,
38    commonware_stability_RESERVED
39)))] // BETA
40pub mod ed25519;
41#[cfg(not(any(
42    commonware_stability_BETA,
43    commonware_stability_GAMMA,
44    commonware_stability_DELTA,
45    commonware_stability_EPSILON,
46    commonware_stability_RESERVED
47)))] // ALPHA
48pub mod secp256r1;
49
50commonware_macros::stability_scope!(ALPHA {
51    #[cfg(feature = "std")]
52    pub mod banderwagon;
53    pub mod bloomfilter;
54    pub use crate::bloomfilter::BloomFilter;
55
56    #[cfg(any(test, feature = "fuzz"))]
57    pub mod fuzz;
58
59    pub mod keccak256;
60    pub use crate::keccak256::{CoreKeccak256, Keccak256};
61
62    pub mod lthash;
63    pub use crate::lthash::LtHash;
64
65    pub mod reed_solomon;
66
67    pub mod sha512;
68    pub use crate::sha512::{CoreSha512, Sha512};
69
70    pub mod zk;
71});
72commonware_macros::stability_scope!(BETA {
73    #[cfg(not(feature = "std"))]
74    use alloc::{sync::Arc, vec::Vec};
75    use commonware_codec::{BufsMut, Encode, EncodeSize, ReadExt, Write};
76    use commonware_math::algebra::Random;
77    use commonware_parallel::Strategy;
78    use commonware_utils::Array;
79    use core::{fmt, future::Future, num::NonZeroUsize};
80    use rand_chacha::ChaCha20Rng;
81    use rand_core::{CryptoRng, SeedableRng as _};
82    #[cfg(feature = "std")]
83    use std::{sync::Arc, vec::Vec};
84
85    pub mod secret;
86    pub use crate::secret::Secret;
87
88    pub mod certificate;
89    pub mod transcript;
90
91    pub mod sha256;
92    pub use crate::sha256::{CoreSha256, Sha256};
93    pub mod blake3;
94    pub use crate::blake3::{Blake3, CoreBlake3};
95    #[cfg(feature = "std")]
96    pub mod crc32;
97    #[cfg(feature = "std")]
98    pub use crate::crc32::Crc32;
99
100    #[cfg(feature = "std")]
101    pub mod chacha20_poly1305;
102    #[cfg(feature = "std")]
103    pub use crate::chacha20_poly1305::ChaCha20Poly1305;
104
105    #[cfg(feature = "std")]
106    pub mod handshake;
107
108    /// Produces [Signature]s over messages that can be verified with a corresponding [PublicKey].
109    pub trait Signer: Random + Send + Sync + Clone + 'static {
110        /// The type of [Signature] produced by this [Signer].
111        type Signature: Signature;
112
113        /// The corresponding [PublicKey] type.
114        type PublicKey: PublicKey<Signature = Self::Signature>;
115
116        /// Returns the [PublicKey] corresponding to this [Signer].
117        fn public_key(&self) -> Self::PublicKey;
118
119        /// Sign a message with the given namespace.
120        ///
121        /// The message should not be hashed prior to calling this function. If a particular scheme
122        /// requires a payload to be hashed before it is signed, it will be done internally.
123        ///
124        /// A namespace must be used to prevent cross-domain attacks (where a signature can be reused
125        /// in a different context). It must be prepended to the message so that a signature meant for
126        /// one context cannot be used unexpectedly in another (i.e. signing a message on the network
127        /// layer can't accidentally spend funds on the execution layer). See
128        /// [commonware_utils::union_unique] for details.
129        fn sign(&self, namespace: &[u8], msg: &[u8]) -> Self::Signature;
130
131        /// Create a [Signer] from a seed.
132        ///
133        /// # Warning
134        ///
135        /// This function is insecure and should only be used for examples
136        /// and testing.
137        fn from_seed(seed: u64) -> Self {
138            Self::random(ChaCha20Rng::seed_from_u64(seed))
139        }
140    }
141
142    /// A [Signer] that can be serialized/deserialized.
143    pub trait PrivateKey: Signer + Sized + ReadExt + Encode {}
144
145    /// Verifies [Signature]s over messages.
146    pub trait Verifier {
147        /// The type of [Signature] that this verifier can verify.
148        type Signature: Signature;
149
150        /// Verify that a [Signature] is a valid over a given message.
151        ///
152        /// The message should not be hashed prior to calling this function. If a particular
153        /// scheme requires a payload to be hashed before it is signed, it will be done internally.
154        ///
155        /// Because namespace is prepended to message before signing, the namespace provided here must
156        /// match the namespace provided during signing.
157        fn verify(&self, namespace: &[u8], msg: &[u8], sig: &Self::Signature) -> bool;
158    }
159
160    /// A [PublicKey], able to verify [Signature]s.
161    pub trait PublicKey: Verifier + Sized + ReadExt + Array {}
162
163    /// A [Signature] over a message.
164    pub trait Signature: Sized + ReadExt + Array {}
165
166    /// An extension of [Signature] that supports public key recovery.
167    pub trait Recoverable: Signature {
168        /// The type of [PublicKey] that can be recovered from this [Signature].
169        type PublicKey: PublicKey<Signature = Self>;
170
171        /// Recover the [PublicKey] of the signer that created this [Signature] over the given message.
172        ///
173        /// The message should not be hashed prior to calling this function. If a particular
174        /// scheme requires a payload to be hashed before it is signed, it will be done internally.
175        ///
176        /// Like when verifying a signature, the namespace must match what was used during signing exactly.
177        fn recover_signer(&self, namespace: &[u8], msg: &[u8]) -> Option<Self::PublicKey>;
178    }
179
180    /// A borrowed view of one signature and the message it authenticates.
181    #[derive(Clone)]
182    pub struct BatchEntry<'a, P: PublicKey> {
183        /// The namespace used during signing.
184        pub namespace: &'a [u8],
185        /// The message used during signing.
186        pub message: &'a [u8],
187        /// The signer's public key.
188        pub public_key: &'a P,
189        /// The signature to verify.
190        pub signature: &'a P::Signature,
191    }
192
193    impl<P: PublicKey> Copy for BatchEntry<'_, P> {}
194
195    /// A [PublicKey] that supports batch verification of [Signature]s.
196    pub trait BatchVerifier: PublicKey {
197        /// Verify all signatures projected from a slice of items.
198        ///
199        /// The projection receives each item's original slice index. It must
200        /// return the same entry for a given index and item.
201        ///
202        /// Messages should not be hashed before calling this function. Any hashing
203        /// required by the signature scheme is performed internally.
204        ///
205        /// Each namespace must match the one used during signing exactly. Use distinct
206        /// namespaces for distinct signing contexts to prevent replay attacks. For
207        /// example, a signature on a message in the network layer must not authorize
208        /// spending funds in the execution layer.
209        ///
210        /// Returns `false` if the slice is empty or any signature is invalid.
211        ///
212        /// # Examples
213        ///
214        /// ```
215        /// use commonware_cryptography::{
216        ///     BatchEntry, BatchVerifier, Signer,
217        ///     ed25519::{PrivateKey, PublicKey},
218        /// };
219        /// use commonware_math::algebra::Random;
220        /// use commonware_parallel::Sequential;
221        /// use commonware_utils::test_rng;
222        ///
223        /// let key = PrivateKey::random(test_rng());
224        /// let public_key = key.public_key();
225        /// let namespace = b"example";
226        /// let records = [(b"message".as_slice(), key.sign(namespace, b"message"))];
227        /// assert!(PublicKey::verify_batch(
228        ///     &mut test_rng(),
229        ///     &records,
230        ///     |_, (message, signature)| BatchEntry {
231        ///         namespace,
232        ///         message,
233        ///         public_key: &public_key,
234        ///         signature,
235        ///     },
236        ///     &Sequential,
237        /// ));
238        /// ```
239        ///
240        /// # Why Randomness?
241        ///
242        /// When performing batch verification, it is often important to add some randomness
243        /// to prevent an attacker from constructing a malicious batch of signatures that pass
244        /// batch verification but are invalid individually. Abstractly, think of this as
245        /// there existing two valid signatures (`c_1` and `c_2`) and an attacker proposing
246        /// (`c_1 + d` and `c_2 - d`).
247        ///
248        /// You can read more about this [here](https://ethresear.ch/t/security-of-bls-batch-verification/10748#the-importance-of-randomness-4).
249        fn verify_batch<'a, R, T, F>(
250            rng: &mut R,
251            items: &'a [T],
252            project: F,
253            strategy: &impl Strategy,
254        ) -> bool
255        where
256            R: CryptoRng,
257            T: Sync,
258            F: Fn(usize, &'a T) -> BatchEntry<'a, Self> + Sync;
259    }
260
261    /// Specializes the [commonware_utils::Array] trait with the Copy trait for cryptographic digests
262    /// (which should be cheap to clone).
263    ///
264    /// # Warning
265    ///
266    /// This trait requires [`Random::random`], but generating a digest at random is
267    /// typically reserved for testing, and not production use.
268    pub trait Digest: Array + Copy + Random {
269        /// An empty (all-zero) digest.
270        const EMPTY: Self;
271    }
272
273    /// An object that can be uniquely represented as a [Digest].
274    pub trait Digestible: Clone + Sized + Send + Sync + 'static {
275        /// The type of digest produced by this object.
276        type Digest: Digest;
277
278        /// Returns a unique representation of the object as a [Digest].
279        ///
280        /// If many objects with [Digest]s are related (map to some higher-level
281        /// group [Digest]), you should also implement [Committable].
282        fn digest(&self) -> Self::Digest;
283
284        /// Returns the object's digest, splitting any work in computing it across `strategy`.
285        fn digest_across(&self, _strategy: &impl Strategy) -> Self::Digest {
286            self.digest()
287        }
288    }
289
290    impl<T: Digestible> Digestible for Arc<T> {
291        type Digest = T::Digest;
292
293        fn digest(&self) -> Self::Digest {
294            self.as_ref().digest()
295        }
296
297        fn digest_across(&self, strategy: &impl Strategy) -> Self::Digest {
298            self.as_ref().digest_across(strategy)
299        }
300    }
301
302    /// A shared value paired with its [Digest].
303    ///
304    /// [`Digested::compute`] hashes the value as a job on a [Strategy], and
305    /// [`Digested::precomputed`] pairs it with a digest a local source already computed from this
306    /// exact value. Holders read the digest for free and never choose a strategy. The value must
307    /// not change anything its digest covers while a carrier refers to it.
308    ///
309    /// Cloning shares the value. Two values are equal when their digests are equal, which the
310    /// [Digestible] contract makes equivalent to the values being equal. The value encodes as the
311    /// inner value does, and there is no decoding. A decoded value is paired with its digest by
312    /// one of the constructors.
313    pub struct Digested<T: Digestible> {
314        inner: Arc<T>,
315        digest: T::Digest,
316    }
317
318    impl<T: Digestible> Digested<T> {
319        /// Computes the digest of `inner` as a job on `strategy`.
320        #[track_caller]
321        pub fn compute(
322            inner: impl Into<Arc<T>>,
323            strategy: &impl Strategy,
324        ) -> impl Future<Output = Self> + Send + 'static
325        where
326            T: EncodeSize,
327        {
328            let inner: Arc<T> = inner.into();
329            strategy.spawn(inner.encode_size(), move |strategy| {
330                let digest = inner.digest_across(&strategy);
331                Self { inner, digest }
332            })
333        }
334
335        /// Pairs `inner` with a digest already computed from this exact value.
336        ///
337        /// `digest` must come from a local source bound to `inner`, such as the key the value was
338        /// stored under, a commitment checked against its bytes, or an earlier [`Self::compute`].
339        /// It says nothing about whether the value is valid or certified.
340        pub fn precomputed(inner: impl Into<Arc<T>>, digest: T::Digest) -> Self {
341            Self {
342                inner: inner.into(),
343                digest,
344            }
345        }
346
347        /// Returns a reference to the value.
348        pub fn inner(&self) -> &T {
349            &self.inner
350        }
351
352        /// Returns a shared reference to the value.
353        pub fn inner_shared(&self) -> Arc<T> {
354            Arc::clone(&self.inner)
355        }
356    }
357
358    impl<T: Digestible> Clone for Digested<T> {
359        fn clone(&self) -> Self {
360            Self {
361                inner: Arc::clone(&self.inner),
362                digest: self.digest,
363            }
364        }
365    }
366
367    impl<T: Digestible + fmt::Debug> fmt::Debug for Digested<T> {
368        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369            f.debug_struct("Digested")
370                .field("digest", &self.digest)
371                .field("inner", &self.inner)
372                .finish()
373        }
374    }
375
376    impl<T: Digestible> PartialEq for Digested<T> {
377        fn eq(&self, other: &Self) -> bool {
378            self.digest == other.digest
379        }
380    }
381
382    impl<T: Digestible> Eq for Digested<T> {}
383
384    impl<T: Digestible> Digestible for Digested<T> {
385        type Digest = T::Digest;
386
387        fn digest(&self) -> Self::Digest {
388            self.digest
389        }
390    }
391
392    impl<T: Digestible + Write> Write for Digested<T> {
393        fn write(&self, buf: &mut impl bytes::BufMut) {
394            self.inner.write(buf);
395        }
396
397        fn write_bufs(&self, buf: &mut impl BufsMut) {
398            self.inner.write_bufs(buf);
399        }
400    }
401
402    impl<T: Digestible + EncodeSize> EncodeSize for Digested<T> {
403        fn encode_size(&self) -> usize {
404            self.inner.encode_size()
405        }
406
407        fn encode_inline_size(&self) -> usize {
408            self.inner.encode_inline_size()
409        }
410    }
411
412    impl<T: Digestible> From<Digested<T>> for Arc<T> {
413        fn from(digested: Digested<T>) -> Self {
414            digested.inner
415        }
416    }
417
418    #[cfg(feature = "arbitrary")]
419    impl<'a, T> arbitrary::Arbitrary<'a> for Digested<T>
420    where
421        T: Digestible + arbitrary::Arbitrary<'a>,
422    {
423        fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
424            let inner = T::arbitrary(u)?;
425            let digest = inner.digest();
426            Ok(Self::precomputed(inner, digest))
427        }
428    }
429
430    /// An object that can produce a commitment of itself.
431    pub trait Committable: Clone + Sized + Send + Sync + 'static {
432        /// The type of commitment produced by this object.
433        type Commitment: Digest;
434
435        /// Returns the unique commitment of the object as a [Digest].
436        ///
437        /// For simple objects (like a block), this is often just the digest of the object
438        /// itself. For more complex objects, however, this may represent some root or base
439        /// of a proof structure (where many unique objects map to the same commitment).
440        ///
441        /// # Warning
442        ///
443        /// It must not be possible for two objects with the same [Digest] to map
444        /// to different commitments. Primitives assume there is a one-to-one
445        /// relation between digest and commitment and a one-to-many relation
446        /// between commitment and digest.
447        fn commitment(&self) -> Self::Commitment;
448    }
449
450    pub type DigestOf<H> = <H as Hasher>::Digest;
451
452    /// Interface that commonware crates rely on for hashing.
453    ///
454    /// Hash functions in commonware primitives are not typically hardcoded
455    /// to a specific algorithm (e.g. SHA-256) because different hash functions
456    /// may work better with different cryptographic schemes, may be more efficient
457    /// to use in STARK/SNARK proofs, or provide different levels of security (with some
458    /// performance/size penalty).
459    ///
460    /// Hashers are cheap to construct: callers that need a fresh hasher should
461    /// create one with [`Default`] rather than duplicating an existing instance.
462    pub trait Hasher: Default + Send + Sync + 'static {
463        /// Digest generated by the hasher.
464        type Digest: Digest;
465
466        /// Hash the concatenation of `parts` in a single shot.
467        ///
468        /// This is the preferred entrypoint for hashing data that is fully
469        /// available up-front. Implementations are free to specialize this for
470        /// small, fixed-shape inputs (e.g. hashing a pair of digests) to avoid
471        /// the overhead of the streaming machinery.
472        fn hash(parts: &[&[u8]]) -> Self::Digest;
473
474        /// Hash the concatenation of `parts` in a single shot, splitting the
475        /// work across `strategy` when the hash function allows it.
476        ///
477        /// Returns the same digest as [`Hasher::hash`], which the default
478        /// implementation calls.
479        fn hash_across(parts: &[&[u8]], _strategy: &impl Strategy) -> Self::Digest {
480            Self::hash(parts)
481        }
482
483        /// Hash two messages, each given as a concatenation of parts, in a
484        /// single shot, splitting the work across `strategy` when the hash
485        /// function allows it.
486        ///
487        /// Must be equivalent to hashing each message with [`Hasher::hash`].
488        fn hash_pair(
489            left: &[&[u8]],
490            right: &[&[u8]],
491            strategy: &impl Strategy,
492        ) -> (Self::Digest, Self::Digest);
493
494        /// Hash multiple independent byte slices, splitting them across
495        /// `strategy`.
496        ///
497        /// Returns one digest per input in the same order. Inputs may be empty,
498        /// differ in length, or overlap. Output position `i` is equivalent to
499        /// `Self::hash(&[messages[i].as_ref()])`.
500        fn hash_many<M: AsRef<[u8]> + Sync>(
501            messages: &[M],
502            strategy: &impl Strategy,
503        ) -> Vec<Self::Digest> {
504            hash_batches(messages, 1, strategy, |batch| {
505                batch
506                    .iter()
507                    .map(|message| Self::hash_across(&[message.as_ref()], strategy))
508                    .collect()
509            })
510        }
511
512        /// Append `bytes` to the hasher's running state.
513        fn update(&mut self, bytes: &[u8]) -> &mut Self;
514
515        /// Consume the hasher, returning a freshly-reset hasher alongside the
516        /// digest of everything written so far.
517        fn finalize(self) -> (Self, Self::Digest);
518    }
519
520    /// Hash `messages` in strategy-supplied batches of whole units of `lanes` (at least one)
521    /// messages, so a kernel that hashes `lanes` messages at once finds every unit but the last
522    /// one full.
523    ///
524    /// `hash` must return one digest per message of its batch, in order. The work estimate is
525    /// the total length of the messages in bytes.
526    pub(crate) fn hash_batches<D, M>(
527        messages: &[M],
528        lanes: usize,
529        strategy: &impl Strategy,
530        hash: impl Fn(&[M]) -> Vec<D> + Sync,
531    ) -> Vec<D>
532    where
533        D: Clone + Send,
534        M: AsRef<[u8]> + Sync,
535    {
536        if messages.is_empty() {
537            return Vec::new();
538        }
539        let units = messages.len().div_ceil(lanes);
540        let bytes = messages.iter().fold(0usize, |bytes, message| {
541            bytes.saturating_add(message.as_ref().len())
542        });
543        strategy.run_batches(units, NonZeroUsize::MIN, bytes.div_ceil(units), |batches| {
544            // A serial run hashes the whole input as one batch, whose digests need no copy.
545            if batches.is_whole() {
546                return hash(messages);
547            }
548            batches
549                .map_collect_vec(
550                    |ranges| {
551                        ranges.into_iter().map(|range| {
552                            let end = range.end.saturating_mul(lanes).min(messages.len());
553                            &messages[range.start * lanes..end]
554                        })
555                    },
556                    &hash,
557                )
558                .concat()
559        })
560    }
561
562    /// Authenticated encryption of an ordered sequence of messages.
563    ///
564    /// Every message is encrypted and authenticated with its associated data. The nth call to
565    /// [Cipher::open] accepts only the nth message sealed under the same key, so replayed,
566    /// reordered, or modified messages fail to open. A failed call consumes the cipher. At most
567    /// one instance may seal under a given key.
568    pub trait Cipher: Random + Sized + Send + Sync + 'static {
569        /// Authentication tag produced for each message.
570        type Tag: Array;
571
572        /// Encrypts the next message in place, authenticated together with `aad`, and returns
573        /// the cipher with the tag.
574        ///
575        /// Returns `None` if sealing fails, in which case the contents of `data` are unspecified.
576        #[must_use = "the cipher is returned only if sealing succeeds"]
577        fn seal(self, aad: &[u8], data: &mut [u8]) -> Option<(Self, Self::Tag)>;
578
579        /// Decrypts the next message in place if `tag` authenticates it together with `aad`, and
580        /// returns the cipher.
581        ///
582        /// Returns `None` if opening fails, in which case the contents of `data` are unspecified.
583        #[must_use = "data is authentic only if opening succeeds"]
584        fn open(self, aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> Option<Self>;
585    }
586});
587
588#[cfg(test)]
589mod tests {
590    use super::*;
591    use commonware_codec::{DecodeExt, FixedSize};
592    use commonware_parallel::mocks::{Explorer, pooled};
593    use commonware_utils::{NZUsize, test_rng};
594    use std::collections::HashSet;
595
596    fn test_validate<C: PrivateKey>() {
597        let mut rng = test_rng();
598        let private_key = C::random(&mut rng);
599        let public_key = private_key.public_key();
600        let decoded = C::PublicKey::decode(commonware_codec::Copying(public_key.as_ref())).unwrap();
601        assert_eq!(public_key, decoded);
602        assert_eq!(public_key.cmp(&decoded), core::cmp::Ordering::Equal);
603
604        let other = C::random(&mut rng).public_key();
605        assert_ne!(public_key, other);
606        let mut keys = HashSet::from([public_key]);
607        assert!(!keys.insert(decoded));
608        assert!(keys.insert(other));
609    }
610
611    fn test_public_key_order<C: PrivateKey>() {
612        let mut rng = test_rng();
613        let mut keys = Vec::new();
614        for _ in 0..16 {
615            let key = C::random(&mut rng).public_key();
616            let decoded = C::PublicKey::decode(commonware_codec::Copying(key.as_ref())).unwrap();
617            keys.extend([key, decoded]);
618        }
619
620        for a in &keys {
621            for b in &keys {
622                let expected = a.as_ref().cmp(b.as_ref());
623                assert_eq!(a.cmp(b), expected);
624                assert_eq!(a.partial_cmp(b), Some(expected));
625                assert_eq!(a == b, expected.is_eq());
626            }
627        }
628    }
629
630    fn test_validate_invalid_public_key<C: Signer>() {
631        let result = C::PublicKey::decode(vec![0; 1024]);
632        assert!(result.is_err());
633    }
634
635    fn test_sign_and_verify<C: PrivateKey>() {
636        let private_key = C::from_seed(0);
637        let namespace = b"test_namespace";
638        let message = b"test_message";
639        let signature = private_key.sign(namespace, message);
640        let public_key = private_key.public_key();
641        assert!(public_key.verify(namespace, message, &signature));
642    }
643
644    fn test_sign_and_verify_wrong_message<C: PrivateKey>() {
645        let private_key = C::from_seed(0);
646        let namespace = b"test_namespace";
647        let message = b"test_message";
648        let wrong_message = b"wrong_message";
649        let signature = private_key.sign(namespace, message);
650        let public_key = private_key.public_key();
651        assert!(!public_key.verify(namespace, wrong_message, &signature));
652    }
653
654    fn test_sign_and_verify_wrong_namespace<C: PrivateKey>() {
655        let private_key = C::from_seed(0);
656        let namespace = b"test_namespace";
657        let wrong_namespace = b"wrong_namespace";
658        let message = b"test_message";
659        let signature = private_key.sign(namespace, message);
660        let public_key = private_key.public_key();
661        assert!(!public_key.verify(wrong_namespace, message, &signature));
662    }
663
664    fn test_empty_namespace<C: PrivateKey>() {
665        let private_key = C::from_seed(0);
666        let empty_namespace = b"";
667        let message = b"test_message";
668        let signature = private_key.sign(empty_namespace, message);
669        let public_key = private_key.public_key();
670        assert!(public_key.verify(empty_namespace, message, &signature));
671    }
672
673    fn test_signature_determinism<C: PrivateKey>() {
674        let private_key_1 = C::from_seed(0);
675        let private_key_2 = C::from_seed(0);
676        let namespace = b"test_namespace";
677        let message = b"test_message";
678        let signature_1 = private_key_1.sign(namespace, message);
679        let signature_2 = private_key_2.sign(namespace, message);
680        assert_eq!(private_key_1.public_key(), private_key_2.public_key());
681        assert_eq!(signature_1, signature_2);
682    }
683
684    fn test_invalid_signature_publickey_pair<C: PrivateKey>() {
685        let private_key = C::from_seed(0);
686        let private_key_2 = C::from_seed(1);
687        let namespace = b"test_namespace";
688        let message = b"test_message";
689        let signature = private_key.sign(namespace, message);
690        let public_key = private_key_2.public_key();
691        assert!(!public_key.verify(namespace, message, &signature));
692    }
693
694    #[test]
695    fn test_ed25519_validate() {
696        test_validate::<ed25519::PrivateKey>();
697    }
698
699    #[test]
700    fn test_ed25519_validate_invalid_public_key() {
701        test_validate_invalid_public_key::<ed25519::PrivateKey>();
702    }
703
704    #[test]
705    fn test_ed25519_sign_and_verify() {
706        test_sign_and_verify::<ed25519::PrivateKey>();
707    }
708
709    #[test]
710    fn test_ed25519_sign_and_verify_wrong_message() {
711        test_sign_and_verify_wrong_message::<ed25519::PrivateKey>();
712    }
713
714    #[test]
715    fn test_ed25519_sign_and_verify_wrong_namespace() {
716        test_sign_and_verify_wrong_namespace::<ed25519::PrivateKey>();
717    }
718
719    #[test]
720    fn test_ed25519_empty_namespace() {
721        test_empty_namespace::<ed25519::PrivateKey>();
722    }
723
724    #[test]
725    fn test_ed25519_signature_determinism() {
726        test_signature_determinism::<ed25519::PrivateKey>();
727    }
728
729    #[test]
730    fn test_ed25519_invalid_signature_publickey_pair() {
731        test_invalid_signature_publickey_pair::<ed25519::PrivateKey>();
732    }
733
734    #[test]
735    fn test_ed25519_len() {
736        assert_eq!(ed25519::PublicKey::SIZE, 32);
737        assert_eq!(ed25519::Signature::SIZE, 64);
738    }
739
740    #[test]
741    #[cfg(feature = "bls12381")]
742    fn test_bls12381_validate() {
743        test_validate::<bls12381::PrivateKey>();
744    }
745
746    #[test]
747    #[cfg(feature = "bls12381")]
748    fn test_bls12381_validate_invalid_public_key() {
749        test_validate_invalid_public_key::<bls12381::PrivateKey>();
750    }
751
752    #[test]
753    #[cfg(feature = "bls12381")]
754    fn test_bls12381_sign_and_verify() {
755        test_sign_and_verify::<bls12381::PrivateKey>();
756    }
757
758    #[test]
759    #[cfg(feature = "bls12381")]
760    fn test_bls12381_sign_and_verify_wrong_message() {
761        test_sign_and_verify_wrong_message::<bls12381::PrivateKey>();
762    }
763
764    #[test]
765    #[cfg(feature = "bls12381")]
766    fn test_bls12381_sign_and_verify_wrong_namespace() {
767        test_sign_and_verify_wrong_namespace::<bls12381::PrivateKey>();
768    }
769
770    #[test]
771    #[cfg(feature = "bls12381")]
772    fn test_bls12381_empty_namespace() {
773        test_empty_namespace::<bls12381::PrivateKey>();
774    }
775
776    #[test]
777    #[cfg(feature = "bls12381")]
778    fn test_bls12381_signature_determinism() {
779        test_signature_determinism::<bls12381::PrivateKey>();
780    }
781
782    #[test]
783    #[cfg(feature = "bls12381")]
784    fn test_bls12381_invalid_signature_publickey_pair() {
785        test_invalid_signature_publickey_pair::<bls12381::PrivateKey>();
786    }
787
788    #[test]
789    #[cfg(feature = "bls12381")]
790    fn test_bls12381_len() {
791        assert_eq!(bls12381::PublicKey::SIZE, 48);
792        assert_eq!(bls12381::Signature::SIZE, 96);
793    }
794
795    #[test]
796    fn test_secp256r1_standard_validate() {
797        test_validate::<secp256r1::standard::PrivateKey>();
798    }
799
800    #[test]
801    fn test_secp256r1_standard_public_key_order() {
802        test_public_key_order::<secp256r1::standard::PrivateKey>();
803    }
804
805    #[test]
806    fn test_secp256r1_standard_validate_invalid_public_key() {
807        test_validate_invalid_public_key::<secp256r1::standard::PrivateKey>();
808    }
809
810    #[test]
811    fn test_secp256r1_standard_sign_and_verify() {
812        test_sign_and_verify::<secp256r1::standard::PrivateKey>();
813    }
814
815    #[test]
816    fn test_secp256r1_standard_sign_and_verify_wrong_message() {
817        test_sign_and_verify_wrong_message::<secp256r1::standard::PrivateKey>();
818    }
819
820    #[test]
821    fn test_secp256r1_standard_sign_and_verify_wrong_namespace() {
822        test_sign_and_verify_wrong_namespace::<secp256r1::standard::PrivateKey>();
823    }
824
825    #[test]
826    fn test_secp256r1_standard_empty_namespace() {
827        test_empty_namespace::<secp256r1::standard::PrivateKey>();
828    }
829
830    #[test]
831    fn test_secp256r1_standard_signature_determinism() {
832        test_signature_determinism::<secp256r1::standard::PrivateKey>();
833    }
834
835    #[test]
836    fn test_secp256r1_standard_invalid_signature_publickey_pair() {
837        test_invalid_signature_publickey_pair::<secp256r1::standard::PrivateKey>();
838    }
839
840    #[test]
841    fn test_secp256r1_standard_len() {
842        assert_eq!(secp256r1::standard::PublicKey::SIZE, 33);
843        assert_eq!(secp256r1::standard::Signature::SIZE, 64);
844    }
845
846    #[test]
847    fn test_secp256r1_recoverable_validate() {
848        test_validate::<secp256r1::recoverable::PrivateKey>();
849    }
850
851    #[test]
852    fn test_secp256r1_recoverable_public_key_order() {
853        test_public_key_order::<secp256r1::recoverable::PrivateKey>();
854    }
855
856    #[test]
857    fn test_secp256r1_recoverable_validate_invalid_public_key() {
858        test_validate_invalid_public_key::<secp256r1::recoverable::PrivateKey>();
859    }
860
861    #[test]
862    fn test_secp256r1_recoverable_sign_and_verify() {
863        test_sign_and_verify::<secp256r1::recoverable::PrivateKey>();
864    }
865
866    #[test]
867    fn test_secp256r1_recoverable_sign_and_verify_wrong_message() {
868        test_sign_and_verify_wrong_message::<secp256r1::recoverable::PrivateKey>();
869    }
870
871    #[test]
872    fn test_secp256r1_recoverable_sign_and_verify_wrong_namespace() {
873        test_sign_and_verify_wrong_namespace::<secp256r1::recoverable::PrivateKey>();
874    }
875
876    #[test]
877    fn test_secp256r1_recoverable_empty_namespace() {
878        test_empty_namespace::<secp256r1::recoverable::PrivateKey>();
879    }
880
881    #[test]
882    fn test_secp256r1_recoverable_signature_determinism() {
883        test_signature_determinism::<secp256r1::recoverable::PrivateKey>();
884    }
885
886    #[test]
887    fn test_secp256r1_recoverable_invalid_signature_publickey_pair() {
888        test_invalid_signature_publickey_pair::<secp256r1::recoverable::PrivateKey>();
889    }
890
891    #[test]
892    fn test_secp256r1_recoverable_len() {
893        assert_eq!(secp256r1::recoverable::PublicKey::SIZE, 33);
894        assert_eq!(secp256r1::recoverable::Signature::SIZE, 65);
895    }
896
897    fn test_hasher_multiple_runs<H: Hasher>() {
898        // Generate initial hash
899        let mut hasher = H::default();
900        hasher.update(b"hello world");
901        let (hasher, digest) = hasher.finalize();
902        assert!(H::Digest::decode(commonware_codec::Copying(digest.as_ref())).is_ok());
903        assert_eq!(digest.as_ref().len(), H::Digest::SIZE);
904
905        // Reuse the reset hasher returned by finalize
906        let mut hasher = hasher;
907        hasher.update(b"hello world");
908        let (hasher, digest_again) = hasher.finalize();
909        assert!(H::Digest::decode(commonware_codec::Copying(digest_again.as_ref())).is_ok());
910        assert_eq!(digest, digest_again);
911
912        // Hash via the one-shot API
913        let digest_oneshot = H::hash(&[b"hello world"]);
914        assert!(H::Digest::decode(commonware_codec::Copying(digest_oneshot.as_ref())).is_ok());
915        assert_eq!(digest, digest_oneshot);
916
917        // Hash different data
918        let mut hasher = hasher;
919        hasher.update(b"hello mars");
920        let (_, digest_mars) = hasher.finalize();
921        assert!(H::Digest::decode(commonware_codec::Copying(digest_mars.as_ref())).is_ok());
922        assert_ne!(digest, digest_mars);
923    }
924
925    #[test]
926    fn test_keccak256_hasher_multiple_runs() {
927        test_hasher_multiple_runs::<Keccak256>();
928    }
929
930    #[test]
931    fn test_sha256_hasher_multiple_runs() {
932        test_hasher_multiple_runs::<Sha256>();
933    }
934
935    #[test]
936    fn test_sha512_hasher_multiple_runs() {
937        test_hasher_multiple_runs::<Sha512>();
938    }
939
940    /// Shares cut the messages only between whole units of `lanes`, cover every message once,
941    /// and return their digests in input order.
942    #[test]
943    fn test_hash_batches_shares_whole_units() {
944        let strategy = Explorer::parallel(&pooled(NZUsize!(4), NZUsize!(8)));
945        for lanes in [1, 2, 8, 16] {
946            for count in [0, 1, lanes + 1, 3 * lanes, 7 * lanes + 1, 9 * lanes, 100] {
947                // Each message holds its index, and its digest pairs that index with the index of
948                // the first message in its share.
949                let messages: Vec<[u8; 4]> = (0..count as u32).map(u32::to_le_bytes).collect();
950                let digests = hash_batches(&messages, lanes, &strategy, |batch| {
951                    let first = u32::from_le_bytes(batch[0]);
952                    batch
953                        .iter()
954                        .map(|message| (u32::from_le_bytes(*message), first))
955                        .collect()
956                });
957                assert!(digests.iter().map(|&(index, _)| index).eq(0..count as u32));
958
959                // Every unit but the last is whole, so every share but the last holds a multiple
960                // of `lanes` messages.
961                let shares: Vec<_> = digests.chunk_by(|a, b| a.1 == b.1).collect();
962                assert_eq!(shares.len(), count.div_ceil(lanes).min(8));
963                if let Some((_, rest)) = shares.split_last() {
964                    assert!(rest.iter().all(|share| share.len() % lanes == 0));
965                }
966            }
967        }
968    }
969}