#![doc(
html_logo_url = "https://commonware.xyz/imgs/rustdoc_logo.svg",
html_favicon_url = "https://commonware.xyz/favicon.ico"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
use commonware_codec::{Encode, ReadExt};
use commonware_utils::Array;
use rand::SeedableRng as _;
use rand_chacha::ChaCha20Rng;
pub mod bls12381;
pub mod ed25519;
pub mod sha256;
use rand_core::CryptoRngCore;
pub use sha256::{CoreSha256, Sha256};
pub mod blake3;
pub use blake3::{Blake3, CoreBlake3};
pub mod bloomfilter;
pub use bloomfilter::BloomFilter;
#[cfg(feature = "std")]
pub mod handshake;
pub mod lthash;
pub use lthash::LtHash;
pub mod secp256r1;
pub mod transcript;
pub trait Signer: Send + Sync + Clone + 'static {
type Signature: Signature;
type PublicKey: PublicKey<Signature = Self::Signature>;
fn public_key(&self) -> Self::PublicKey;
fn sign(&self, namespace: Option<&[u8]>, msg: &[u8]) -> Self::Signature;
}
pub trait PrivateKey: Signer + Sized + ReadExt + Encode + PartialEq + Array {}
pub trait PrivateKeyExt: PrivateKey {
fn from_seed(seed: u64) -> Self {
let mut rng = ChaCha20Rng::seed_from_u64(seed);
Self::from_rng(&mut rng)
}
fn from_rng<R: CryptoRngCore>(rng: &mut R) -> Self;
}
pub trait Verifier {
type Signature: Signature;
fn verify(&self, namespace: Option<&[u8]>, msg: &[u8], sig: &Self::Signature) -> bool;
}
pub trait PublicKey: Verifier + Sized + ReadExt + Encode + PartialEq + Array {}
pub trait Signature: Sized + Clone + ReadExt + Encode + PartialEq + Array {}
pub trait BatchVerifier<K: PublicKey> {
fn new() -> Self;
fn add(
&mut self,
namespace: Option<&[u8]>,
message: &[u8],
public_key: &K,
signature: &K::Signature,
) -> bool;
fn verify<R: CryptoRngCore>(self, rng: &mut R) -> bool;
}
pub trait Digest: Array + Copy {
fn random<R: CryptoRngCore>(rng: &mut R) -> Self;
}
pub trait Digestible: Clone + Sized + Send + Sync + 'static {
type Digest: Digest;
fn digest(&self) -> Self::Digest;
}
pub trait Committable: Clone + Sized + Send + Sync + 'static {
type Commitment: Digest;
fn commitment(&self) -> Self::Commitment;
}
pub trait Hasher: Default + Clone + Send + Sync + 'static {
type Digest: Digest;
fn new() -> Self {
Self::default()
}
fn update(&mut self, message: &[u8]) -> &mut Self;
fn finalize(&mut self) -> Self::Digest;
fn reset(&mut self) -> &mut Self;
fn empty() -> Self::Digest;
fn hash(message: &[u8]) -> Self::Digest {
Self::new().update(message).finalize()
}
}
#[cfg(test)]
mod tests {
use super::*;
use commonware_codec::{DecodeExt, FixedSize};
use rand::rngs::OsRng;
fn test_validate<C: PrivateKeyExt>() {
let private_key = C::from_rng(&mut OsRng);
let public_key = private_key.public_key();
assert!(C::PublicKey::decode(public_key.as_ref()).is_ok());
}
fn test_validate_invalid_public_key<C: Signer>() {
let result = C::PublicKey::decode(vec![0; 1024].as_ref());
assert!(result.is_err());
}
fn test_sign_and_verify<C: PrivateKeyExt>() {
let private_key = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature = private_key.sign(namespace, message);
let public_key = private_key.public_key();
assert!(public_key.verify(namespace, message, &signature));
}
fn test_sign_and_verify_wrong_message<C: PrivateKeyExt>() {
let private_key = C::from_seed(0);
let namespace: Option<&[u8]> = Some(&b"test_namespace"[..]);
let message = b"test_message";
let wrong_message = b"wrong_message";
let signature = private_key.sign(namespace, message);
let public_key = private_key.public_key();
assert!(!public_key.verify(namespace, wrong_message, &signature));
}
fn test_sign_and_verify_wrong_namespace<C: PrivateKeyExt>() {
let private_key = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let wrong_namespace = Some(&b"wrong_namespace"[..]);
let message = b"test_message";
let signature = private_key.sign(namespace, message);
let public_key = private_key.public_key();
assert!(!public_key.verify(wrong_namespace, message, &signature));
}
fn test_empty_vs_none_namespace<C: PrivateKeyExt>() {
let private_key = C::from_seed(0);
let empty_namespace = Some(&b""[..]);
let message = b"test_message";
let signature = private_key.sign(empty_namespace, message);
let public_key = private_key.public_key();
assert!(public_key.verify(empty_namespace, message, &signature));
assert!(!public_key.verify(None, message, &signature));
}
fn test_signature_determinism<C: PrivateKeyExt>() {
let private_key_1 = C::from_seed(0);
let private_key_2 = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature_1 = private_key_1.sign(namespace, message);
let signature_2 = private_key_2.sign(namespace, message);
assert_eq!(private_key_1.public_key(), private_key_2.public_key());
assert_eq!(signature_1, signature_2);
}
fn test_invalid_signature_publickey_pair<C: PrivateKeyExt>() {
let private_key = C::from_seed(0);
let private_key_2 = C::from_seed(1);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature = private_key.sign(namespace, message);
let public_key = private_key_2.public_key();
assert!(!public_key.verify(namespace, message, &signature));
}
#[test]
fn test_ed25519_validate() {
test_validate::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_validate_invalid_public_key() {
test_validate_invalid_public_key::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_sign_and_verify() {
test_sign_and_verify::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_signature_determinism() {
test_signature_determinism::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<ed25519::PrivateKey>();
}
#[test]
fn test_ed25519_len() {
assert_eq!(ed25519::PublicKey::SIZE, 32);
assert_eq!(ed25519::Signature::SIZE, 64);
}
#[test]
fn test_bls12381_validate() {
test_validate::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_validate_invalid_public_key() {
test_validate_invalid_public_key::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_sign_and_verify() {
test_sign_and_verify::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_signature_determinism() {
test_signature_determinism::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<bls12381::PrivateKey>();
}
#[test]
fn test_bls12381_len() {
assert_eq!(bls12381::PublicKey::SIZE, 48);
assert_eq!(bls12381::Signature::SIZE, 96);
}
#[test]
fn test_secp256r1_validate() {
test_validate::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_validate_invalid_public_key() {
test_validate_invalid_public_key::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_sign_and_verify() {
test_sign_and_verify::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_signature_determinism() {
test_signature_determinism::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<secp256r1::PrivateKey>();
}
#[test]
fn test_secp256r1_len() {
assert_eq!(secp256r1::PublicKey::SIZE, 33);
assert_eq!(secp256r1::Signature::SIZE, 64);
}
fn test_hasher_multiple_runs<H: Hasher>() {
let mut hasher = H::new();
hasher.update(b"hello world");
let digest = hasher.finalize();
assert!(H::Digest::decode(digest.as_ref()).is_ok());
assert_eq!(digest.as_ref().len(), H::Digest::SIZE);
hasher.update(b"hello world");
let digest_again = hasher.finalize();
assert!(H::Digest::decode(digest_again.as_ref()).is_ok());
assert_eq!(digest, digest_again);
hasher.update(b"hello mars");
hasher.reset();
hasher.update(b"hello world");
let digest_reset = hasher.finalize();
assert!(H::Digest::decode(digest_reset.as_ref()).is_ok());
assert_eq!(digest, digest_reset);
hasher.update(b"hello mars");
let digest_mars = hasher.finalize();
assert!(H::Digest::decode(digest_mars.as_ref()).is_ok());
assert_ne!(digest, digest_mars);
}
fn test_hasher_multiple_updates<H: Hasher>() {
let mut hasher = H::new();
hasher.update(b"hello");
hasher.update(b" world");
let digest = hasher.finalize();
assert!(H::Digest::decode(digest.as_ref()).is_ok());
let mut hasher = H::new();
hasher.update(b"hello world");
let digest_oneshot = hasher.finalize();
assert!(H::Digest::decode(digest_oneshot.as_ref()).is_ok());
assert_eq!(digest, digest_oneshot);
}
fn test_hasher_empty_input<H: Hasher>() {
let mut hasher = H::new();
let digest = hasher.finalize();
assert!(H::Digest::decode(digest.as_ref()).is_ok());
}
fn test_hasher_large_input<H: Hasher>() {
let mut hasher = H::new();
let data = vec![1; 1024];
hasher.update(&data);
let digest = hasher.finalize();
assert!(H::Digest::decode(digest.as_ref()).is_ok());
}
#[test]
fn test_sha256_hasher_multiple_runs() {
test_hasher_multiple_runs::<Sha256>();
}
#[test]
fn test_sha256_hasher_multiple_updates() {
test_hasher_multiple_updates::<Sha256>();
}
#[test]
fn test_sha256_hasher_empty_input() {
test_hasher_empty_input::<Sha256>();
}
#[test]
fn test_sha256_hasher_large_input() {
test_hasher_large_input::<Sha256>();
}
}