use crate::error::FastCryptoResult;
use crate::{
encoding::{Base64, Encoding},
error::FastCryptoError,
hash::HashFunction,
};
use rand::rngs::{StdRng, ThreadRng};
use rand::{CryptoRng, RngCore};
use serde::{de::DeserializeOwned, Serialize};
use std::{
borrow::Borrow,
fmt::{Debug, Display},
str::FromStr,
};
pub trait ToFromBytes: AsRef<[u8]> + Debug + Sized {
fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError>;
fn as_bytes(&self) -> &[u8] {
self.as_ref()
}
}
pub trait EncodeDecodeBase64: Sized {
fn encode_base64(&self) -> String;
fn decode_base64(value: &str) -> FastCryptoResult<Self>;
}
impl<T: ToFromBytes> EncodeDecodeBase64 for T {
fn encode_base64(&self) -> String {
Base64::encode(self.as_bytes())
}
fn decode_base64(value: &str) -> FastCryptoResult<Self> {
let bytes = Base64::decode(value)?;
<T as ToFromBytes>::from_bytes(&bytes)
}
}
pub trait VerifyingKey:
Serialize
+ DeserializeOwned
+ std::hash::Hash
+ Display
+ Eq + Ord + ToFromBytes
+ for<'a> From<&'a Self::PrivKey> + Send
+ Sync
+ 'static
+ Clone
{
type PrivKey: SigningKey<PubKey=Self>;
type Sig: Authenticator<PubKey=Self>;
const LENGTH: usize;
fn verify(&self, msg: &[u8], signature: &Self::Sig) -> Result<(), FastCryptoError>;
#[cfg(any(test, feature = "experimental"))]
fn verify_batch_empty_fail(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> FastCryptoResult<()> {
if sigs.is_empty() || pks.len() != sigs.len() {
return Err(FastCryptoError::InvalidInput);
}
pks.iter()
.zip(sigs)
.try_for_each(|(pk, sig)| pk.verify(msg, sig))
}
#[cfg(any(test, feature = "experimental"))]
fn verify_batch_empty_fail_different_msg<'a, M>(msgs: &[M], pks: &[Self], sigs: &[Self::Sig])
-> FastCryptoResult<()> where M: Borrow<[u8]> + 'a {
if sigs.is_empty() || pks.len() != sigs.len() || pks.len() != msgs.len() {
return Err(FastCryptoError::InvalidInput);
}
pks.iter()
.zip(sigs)
.zip(msgs)
.try_for_each(|((pk, sig), msg)| pk.verify(msg.borrow(), sig))
}
}
pub trait SigningKey: ToFromBytes + Serialize + DeserializeOwned + Send + Sync + 'static {
type PubKey: VerifyingKey<PrivKey = Self>;
type Sig: Authenticator<PrivKey = Self>;
const LENGTH: usize;
}
pub trait Authenticator:
ToFromBytes + Display + Serialize + DeserializeOwned + Send + Sync + 'static + Clone
{
type PubKey: VerifyingKey<Sig = Self>;
type PrivKey: SigningKey<Sig = Self>;
const LENGTH: usize;
}
pub trait Signer<Sig> {
fn sign(&self, msg: &[u8]) -> Sig;
}
pub trait KeyPair:
Sized + From<Self::PrivKey> + Signer<Self::Sig> + EncodeDecodeBase64 + FromStr
{
type PubKey: VerifyingKey<PrivKey = Self::PrivKey, Sig = Self::Sig>;
type PrivKey: SigningKey<PubKey = Self::PubKey, Sig = Self::Sig>;
type Sig: Authenticator<PubKey = Self::PubKey, PrivKey = Self::PrivKey>;
fn public(&'_ self) -> &'_ Self::PubKey;
fn private(self) -> Self::PrivKey;
#[cfg(feature = "copy_key")]
fn copy(&self) -> Self;
fn generate<R: AllowedRng>(rng: &mut R) -> Self;
}
pub trait RecoverableSigner {
type PubKey;
type Sig: RecoverableSignature<Signer = Self, PubKey = Self::PubKey>;
fn sign_recoverable(&self, msg: &[u8]) -> Self::Sig {
self.sign_recoverable_with_hash::<<<Self as RecoverableSigner>::Sig as RecoverableSignature>::DefaultHash>(msg)
}
fn sign_recoverable_with_hash<H: HashFunction<32>>(&self, msg: &[u8]) -> Self::Sig;
}
pub trait VerifyRecoverable: Eq + Sized {
type Sig: RecoverableSignature<PubKey = Self>;
fn verify_recoverable(&self, msg: &[u8], signature: &Self::Sig) -> Result<(), FastCryptoError> {
self.verify_recoverable_with_hash::<<<Self as VerifyRecoverable>::Sig as RecoverableSignature>::DefaultHash>(msg, signature)
}
fn verify_recoverable_with_hash<H: HashFunction<32>>(
&self,
msg: &[u8],
signature: &Self::Sig,
) -> Result<(), FastCryptoError> {
match signature.recover_with_hash::<H>(msg)? == *self {
true => Ok(()),
false => Err(FastCryptoError::InvalidSignature),
}
}
}
pub trait RecoverableSignature: Sized {
type PubKey;
type Signer: RecoverableSigner<Sig = Self, PubKey = Self::PubKey>;
type DefaultHash: HashFunction<32>;
fn recover(&self, msg: &[u8]) -> Result<Self::PubKey, FastCryptoError> {
self.recover_with_hash::<Self::DefaultHash>(msg)
}
fn recover_with_hash<H: HashFunction<32>>(
&self,
msg: &[u8],
) -> Result<Self::PubKey, FastCryptoError>;
}
pub trait AggregateAuthenticator:
Display + Serialize + DeserializeOwned + Send + Sync + 'static + Clone
{
type Sig: Authenticator<PubKey = Self::PubKey>;
type PubKey: VerifyingKey<Sig = Self::Sig>;
type PrivKey: SigningKey<Sig = Self::Sig>;
fn aggregate<'a, K: Borrow<Self::Sig> + 'a, I: IntoIterator<Item = &'a K>>(
signatures: I,
) -> Result<Self, FastCryptoError>;
fn add_signature(&mut self, signature: Self::Sig) -> Result<(), FastCryptoError>;
fn add_aggregate(&mut self, signature: Self) -> Result<(), FastCryptoError>;
fn verify(
&self,
pks: &[<Self::Sig as Authenticator>::PubKey],
message: &[u8],
) -> Result<(), FastCryptoError>;
fn verify_different_msg(
&self,
pks: &[<Self::Sig as Authenticator>::PubKey],
messages: &[&[u8]],
) -> Result<(), FastCryptoError>;
fn batch_verify<'a>(
sigs: &[&Self],
pks: Vec<impl ExactSizeIterator<Item = &'a Self::PubKey>>,
messages: &[&[u8]],
) -> Result<(), FastCryptoError>;
}
pub trait Generate {
fn generate<R: AllowedRng>(rng: &mut R) -> Self;
}
pub trait FromUniformBytes<const LENGTH: usize>: ToFromBytes {
fn generate<R: AllowedRng>(rng: &mut R) -> Self {
let mut bytes = [0u8; LENGTH];
rng.fill_bytes(&mut bytes);
Self::from_bytes(&bytes).unwrap()
}
}
pub trait InsecureDefault {
fn insecure_default() -> Self;
}
pub trait AllowedRng: CryptoRng + RngCore {}
impl AllowedRng for StdRng {}
impl AllowedRng for ThreadRng {}