commonware_cryptography/
lib.rsuse bytes::Buf;
use commonware_utils::SizedSerialize;
use rand::{CryptoRng, Rng, RngCore, SeedableRng};
use std::fmt::Display;
use std::{fmt::Debug, hash::Hash, ops::Deref};
use thiserror::Error;
pub mod bls12381;
pub use bls12381::Bls12381;
pub mod ed25519;
pub use ed25519::{Ed25519, Ed25519Batch};
pub mod sha256;
pub use sha256::{hash, Sha256};
pub mod secp256r1;
pub use secp256r1::Secp256r1;
#[derive(Error, Debug, PartialEq)]
pub enum Error {
#[error("invalid digest length")]
InvalidDigestLength,
#[error("invalid private key")]
InvalidPrivateKey,
#[error("invalid private key length")]
InvalidPrivateKeyLength,
#[error("invalid public key")]
InvalidPublicKey,
#[error("invalid public key length")]
InvalidPublicKeyLength,
#[error("invalid signature")]
InvalidSignature,
#[error("invalid signature length")]
InvalidSignatureLength,
#[error("invalid bytes")]
InsufficientBytes,
}
pub trait Array:
Clone
+ Send
+ Sync
+ 'static
+ Eq
+ PartialEq
+ Ord
+ PartialOrd
+ Debug
+ Hash
+ Display
+ AsRef<[u8]>
+ Deref<Target = [u8]>
+ for<'a> TryFrom<&'a [u8], Error = Error>
+ for<'a> TryFrom<&'a Vec<u8>, Error = Error>
+ TryFrom<Vec<u8>, Error = Error>
+ SizedSerialize
{
fn read_from<B: Buf>(buf: &mut B) -> Result<Self, Error> {
let len = Self::SERIALIZED_LEN;
if buf.remaining() < len {
return Err(Error::InsufficientBytes);
}
let chunk = buf.chunk();
if chunk.len() >= len {
let array = Self::try_from(&chunk[..len])?;
buf.advance(len);
return Ok(array);
}
let mut temp = vec![0u8; len];
buf.copy_to_slice(&mut temp);
Self::try_from(temp)
}
}
pub trait Scheme: Clone + Send + Sync + 'static {
type PrivateKey: Array;
type PublicKey: Array;
type Signature: Array;
fn new<R: Rng + CryptoRng>(rng: &mut R) -> Self;
fn from(private_key: Self::PrivateKey) -> Option<Self>;
fn from_seed(seed: u64) -> Self {
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
Self::new(&mut rng)
}
fn private_key(&self) -> Self::PrivateKey;
fn public_key(&self) -> Self::PublicKey;
fn sign(&mut self, namespace: Option<&[u8]>, message: &[u8]) -> Self::Signature;
fn verify(
namespace: Option<&[u8]>,
message: &[u8],
public_key: &Self::PublicKey,
signature: &Self::Signature,
) -> bool;
}
pub trait BatchScheme {
type PublicKey: Array;
type Signature: Array;
fn new() -> Self;
fn add(
&mut self,
namespace: Option<&[u8]>,
message: &[u8],
public_key: &Self::PublicKey,
signature: &Self::Signature,
) -> bool;
fn verify<R: RngCore + CryptoRng>(self, rng: &mut R) -> bool;
}
pub trait Hasher: Clone + Send + Sync + 'static {
type Digest: Array;
fn new() -> Self;
fn update(&mut self, message: &[u8]);
fn finalize(&mut self) -> Self::Digest;
fn reset(&mut self);
fn random<R: Rng + CryptoRng>(rng: &mut R) -> Self::Digest;
}
#[cfg(test)]
mod tests {
use super::*;
use rand::rngs::OsRng;
fn test_validate<C: Scheme>() {
let signer = C::new(&mut OsRng);
let public_key = signer.public_key();
assert!(C::PublicKey::try_from(public_key.as_ref()).is_ok());
}
fn test_from_valid_private_key<C: Scheme>() {
let signer = C::new(&mut OsRng);
let private_key = signer.private_key();
let public_key = signer.public_key();
let signer = C::from(private_key).unwrap();
assert_eq!(public_key, signer.public_key());
}
fn test_validate_invalid_public_key<C: Scheme>() {
let result = C::PublicKey::try_from(vec![0; 1024]);
assert_eq!(result, Err(Error::InvalidPublicKeyLength));
}
fn test_sign_and_verify<C: Scheme>() {
let mut signer = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature = signer.sign(namespace, message);
let public_key = signer.public_key();
assert!(C::verify(namespace, message, &public_key, &signature));
}
fn test_sign_and_verify_wrong_message<C: Scheme>() {
let mut signer = 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 = signer.sign(namespace, message);
let public_key = signer.public_key();
assert!(!C::verify(
namespace,
wrong_message,
&public_key,
&signature
));
}
fn test_sign_and_verify_wrong_namespace<C: Scheme>() {
let mut signer = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let wrong_namespace = Some(&b"wrong_namespace"[..]);
let message = b"test_message";
let signature = signer.sign(namespace, message);
let public_key = signer.public_key();
assert!(!C::verify(
wrong_namespace,
message,
&public_key,
&signature
));
}
fn test_empty_vs_none_namespace<C: Scheme>() {
let mut signer = C::from_seed(0);
let empty_namespace = Some(&b""[..]);
let message = b"test_message";
let signature = signer.sign(empty_namespace, message);
let public_key = signer.public_key();
assert!(C::verify(empty_namespace, message, &public_key, &signature));
assert!(!C::verify(None, message, &public_key, &signature));
}
fn test_signature_determinism<C: Scheme>() {
let mut signer_1 = C::from_seed(0);
let mut signer_2 = C::from_seed(0);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature_1 = signer_1.sign(namespace, message);
let signature_2 = signer_2.sign(namespace, message);
assert_eq!(signer_1.public_key(), signer_2.public_key());
assert_eq!(signature_1, signature_2);
}
fn test_invalid_signature_publickey_pair<C: Scheme>() {
let mut signer = C::from_seed(0);
let signer_2 = C::from_seed(1);
let namespace = Some(&b"test_namespace"[..]);
let message = b"test_message";
let signature = signer.sign(namespace, message);
let public_key = signer_2.public_key();
assert!(!C::verify(namespace, message, &public_key, &signature));
}
#[test]
fn test_ed25519_validate() {
test_validate::<Ed25519>();
}
#[test]
fn test_ed25519_validate_invalid_public_key() {
test_validate_invalid_public_key::<Ed25519>();
}
#[test]
fn test_ed25519_from_valid_private_key() {
test_from_valid_private_key::<Ed25519>();
}
#[test]
fn test_ed25519_sign_and_verify() {
test_sign_and_verify::<Ed25519>();
}
#[test]
fn test_ed25519_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<Ed25519>();
}
#[test]
fn test_ed25519_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<Ed25519>();
}
#[test]
fn test_ed25519_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<Ed25519>();
}
#[test]
fn test_ed25519_signature_determinism() {
test_signature_determinism::<Ed25519>();
}
#[test]
fn test_ed25519_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<Ed25519>();
}
#[test]
fn test_ed25519_len() {
assert_eq!(<Ed25519 as Scheme>::PublicKey::SERIALIZED_LEN, 32);
assert_eq!(<Ed25519 as Scheme>::Signature::SERIALIZED_LEN, 64);
}
#[test]
fn test_bls12381_validate() {
test_validate::<Bls12381>();
}
#[test]
fn test_bls12381_validate_invalid_public_key() {
test_validate_invalid_public_key::<Bls12381>();
}
#[test]
fn test_bls12381_from_valid_private_key() {
test_from_valid_private_key::<Bls12381>();
}
#[test]
fn test_bls12381_sign_and_verify() {
test_sign_and_verify::<Bls12381>();
}
#[test]
fn test_bls12381_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<Bls12381>();
}
#[test]
fn test_bls12381_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<Bls12381>();
}
#[test]
fn test_bls12381_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<Bls12381>();
}
#[test]
fn test_bls12381_signature_determinism() {
test_signature_determinism::<Bls12381>();
}
#[test]
fn test_bls12381_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<Bls12381>();
}
#[test]
fn test_bls12381_len() {
assert_eq!(<Bls12381 as Scheme>::PublicKey::SERIALIZED_LEN, 48);
assert_eq!(<Bls12381 as Scheme>::Signature::SERIALIZED_LEN, 96);
}
#[test]
fn test_secp256r1_validate() {
test_validate::<Secp256r1>();
}
#[test]
fn test_secp256r1_validate_invalid_public_key() {
test_validate_invalid_public_key::<Secp256r1>();
}
#[test]
fn test_secp256r1_from_valid_private_key() {
test_from_valid_private_key::<Secp256r1>();
}
#[test]
fn test_secp256r1_sign_and_verify() {
test_sign_and_verify::<Secp256r1>();
}
#[test]
fn test_secp256r1_sign_and_verify_wrong_message() {
test_sign_and_verify_wrong_message::<Secp256r1>();
}
#[test]
fn test_secp256r1_sign_and_verify_wrong_namespace() {
test_sign_and_verify_wrong_namespace::<Secp256r1>();
}
#[test]
fn test_secp256r1_empty_vs_none_namespace() {
test_empty_vs_none_namespace::<Secp256r1>();
}
#[test]
fn test_secp256r1_signature_determinism() {
test_signature_determinism::<Secp256r1>();
}
#[test]
fn test_secp256r1_invalid_signature_publickey_pair() {
test_invalid_signature_publickey_pair::<Secp256r1>();
}
#[test]
fn test_secp256r1_len() {
assert_eq!(<Secp256r1 as Scheme>::PublicKey::SERIALIZED_LEN, 33);
assert_eq!(<Secp256r1 as Scheme>::Signature::SERIALIZED_LEN, 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::try_from(digest.as_ref()).is_ok());
assert_eq!(digest.as_ref().len(), H::Digest::SERIALIZED_LEN);
hasher.update(b"hello world");
let digest_again = hasher.finalize();
assert!(H::Digest::try_from(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::try_from(digest_reset.as_ref()).is_ok());
assert_eq!(digest, digest_reset);
hasher.update(b"hello mars");
let digest_mars = hasher.finalize();
assert!(H::Digest::try_from(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::try_from(digest.as_ref()).is_ok());
let mut hasher = H::new();
hasher.update(b"hello world");
let digest_oneshot = hasher.finalize();
assert!(H::Digest::try_from(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::try_from(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::try_from(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>();
}
}