use crate::hash::{CryptoHash, CryptoHasher};
use anyhow::Result;
use core::convert::{From, TryFrom};
use rand::{rngs::StdRng, CryptoRng, RngCore, SeedableRng};
use serde::{de::DeserializeOwned, Serialize};
use std::{fmt::Debug, hash::Hash};
use thiserror::Error;
#[derive(Clone, Debug, PartialEq, Eq, Error)]
#[error("{:?}", self)]
pub enum CryptoMaterialError {
SerializationError,
DeserializationError,
ValidationError,
WrongLengthError,
CanonicalRepresentationError,
SmallSubgroupError,
PointNotOnCurveError,
BitVecError(String),
}
pub trait Length {
fn length(&self) -> usize;
}
pub trait ValidCryptoMaterial:
for<'a> TryFrom<&'a [u8], Error=CryptoMaterialError> + Serialize + DeserializeOwned
{
fn to_bytes(&self) -> Vec<u8>;
}
pub trait ValidCryptoMaterialStringExt: ValidCryptoMaterial {
fn from_encoded_string(encoded_str: &str) -> std::result::Result<Self, CryptoMaterialError> {
let encoded_str = encoded_str.strip_prefix("0x").unwrap_or(encoded_str);
let bytes_out = ::hex::decode(encoded_str);
bytes_out
.or(Err(CryptoMaterialError::DeserializationError))
.and_then(|ref bytes| Self::try_from(bytes))
}
fn to_encoded_string(&self) -> Result<String> {
Ok(format!("0x{}", ::hex::encode(&self.to_bytes())))
}
}
impl<T: ValidCryptoMaterial> ValidCryptoMaterialStringExt for T {}
pub trait PrivateKey: Sized {
type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;
fn public_key(&self) -> Self::PublicKeyMaterial {
self.into()
}
}
pub trait SigningKey:
PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial>
+ ValidCryptoMaterial
+ private::Sealed
{
type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
type SignatureMaterial: Signature<SigningKeyMaterial = Self>;
fn sign<T: CryptoHash + Serialize>(&self, message: &T) -> Self::SignatureMaterial;
#[cfg(any(test, feature = "fuzzing"))]
fn sign_arbitrary_message(&self, message: &[u8]) -> Self::SignatureMaterial;
fn verifying_key(&self) -> Self::VerifyingKeyMaterial {
self.public_key()
}
}
pub fn signing_message<T: CryptoHash + Serialize>(message: &T) -> Vec<u8> {
let mut bytes = <T::Hasher as CryptoHasher>::seed().to_vec();
bcs::serialize_into(&mut bytes, &message)
.map_err(|_| CryptoMaterialError::SerializationError)
.expect("Serialization of signable material should not fail.");
bytes
}
pub trait PublicKey: Sized + Clone + Eq + Hash + ValidCryptoMaterial +
for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
}
pub trait VerifyingKey:
PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial>
+ ValidCryptoMaterial
+ private::Sealed
{
type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;
fn verify_struct_signature<T: CryptoHash + Serialize>(
&self,
message: &T,
signature: &Self::SignatureMaterial,
) -> Result<()> {
signature.verify(message, self)
}
fn batch_verify<T: CryptoHash + Serialize>(
message: &T,
keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
) -> Result<()> {
Self::SignatureMaterial::batch_verify(message, keys_and_signatures)
}
}
pub trait Signature:
for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError>
+ Sized
+ Debug
+ Clone
+ Eq
+ Hash
+ private::Sealed
{
type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;
fn verify<T: CryptoHash + Serialize>(
&self,
message: &T,
public_key: &Self::VerifyingKeyMaterial,
) -> Result<()>;
fn verify_arbitrary_msg(
&self,
message: &[u8],
public_key: &Self::VerifyingKeyMaterial,
) -> Result<()>;
fn to_bytes(&self) -> Vec<u8>;
fn batch_verify<T: CryptoHash + Serialize>(
message: &T,
keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
) -> Result<()> {
for (key, signature) in keys_and_signatures {
signature.verify(message, &key)?
}
Ok(())
}
}
pub trait Uniform {
fn generate<R>(rng: &mut R) -> Self
where
R: RngCore + CryptoRng;
fn generate_for_testing() -> Self
where
Self: Sized,
{
let mut rng: StdRng = SeedableRng::from_seed(crate::test_utils::TEST_SEED);
Self::generate(&mut rng)
}
}
pub trait Genesis: PrivateKey {
fn genesis() -> Self;
}
pub(crate) mod private {
pub trait Sealed {}
impl Sealed for crate::ed25519::Ed25519PrivateKey {}
impl Sealed for crate::ed25519::Ed25519PublicKey {}
impl Sealed for crate::ed25519::Ed25519Signature {}
impl Sealed for crate::multi_ed25519::MultiEd25519PrivateKey {}
impl Sealed for crate::multi_ed25519::MultiEd25519PublicKey {}
impl Sealed for crate::multi_ed25519::MultiEd25519Signature {}
impl Sealed for crate::bls12381::PrivateKey {}
impl Sealed for crate::bls12381::PublicKey {}
impl Sealed for crate::bls12381::Signature {}
impl Sealed for crate::bls12381::ProofOfPossession {}
}