use crate::error::*;
use ed25519_dalek::{
ed25519::signature::Signature as _,
Keypair as Ed25519Keypair,
PublicKey as Ed25519Pubkey,
SecretKey as Ed25519Seckey,
Signature as Ed25519Signature,
Signer as _,
Verifier as _
};
use pqcrypto_dilithium::dilithium3::{
detached_sign,
keypair,
verify_detached_signature,
DetachedSignature as Dilithium3Signature,
PublicKey as Dilithium3Pubkey,
SecretKey as Dilithium3Seckey
};
use pqcrypto_traits::sign::*;
use rand_core::OsRng;
pub enum AnySignature {
Ed25519(Ed25519Signature),
Dilithium3(Box<Dilithium3Signature>)
}
impl AnySignature {
pub fn new(name: &str, bytes: &[u8]) -> Result<Self> {
Ok(match name {
"ed25519" => Self::Ed25519(Ed25519Signature::from_bytes(bytes)
.map_err(|_| Error::InvalidSignature)?),
"dilithium3" => Self::Dilithium3(Box::new(Dilithium3Signature::from_bytes(bytes)
.map_err(|_| Error::InvalidSignature)?)),
_ => return Err(Error::UnsupportedAlgorithm)
})
}
pub fn name(&self) -> &'static str {
match self {
Self::Ed25519(_) => "ed25519",
Self::Dilithium3(_) => "dilithium3"
}
}
pub fn to_bytes(&self) -> Vec<u8> {
match self {
Self::Ed25519(sig) => sig.as_bytes().to_vec(),
Self::Dilithium3(sig) => sig.as_bytes().to_vec()
}
}
}
pub enum AnyPubkey {
Ed25519(Ed25519Pubkey),
Dilithium3(Box<Dilithium3Pubkey>)
}
impl AnyPubkey {
pub fn new(name: &str, bytes: &[u8]) -> Result<Self> {
Ok(match name {
"ed25519" => Self::Ed25519(Ed25519Pubkey::from_bytes(bytes)
.map_err(|_| Error::InvalidData)?),
"dilithium3" => Self::Dilithium3(Box::new(Dilithium3Pubkey::from_bytes(bytes)
.map_err(|_| Error::InvalidData)?)),
_ => return Err(Error::UnsupportedAlgorithm)
})
}
pub fn name(&self) -> &'static str {
match self {
Self::Ed25519(_) => "ed25519",
Self::Dilithium3(_) => "dilithium3"
}
}
pub fn as_bytes(&self) -> &[u8] {
match self {
Self::Ed25519(pubkey) => pubkey.as_bytes(),
Self::Dilithium3(pubkey) => pubkey.as_bytes()
}
}
pub fn verify(&self, challenge: &[u8], sig: &AnySignature) -> Result<()> {
match self {
Self::Ed25519(pubkey) => match sig {
AnySignature::Ed25519(sig) => pubkey.verify(challenge, sig)
.map_err(|_| Error::InvalidSignature),
_ => Err(Error::UnsupportedAlgorithm)
},
Self::Dilithium3(pubkey) => match sig {
AnySignature::Dilithium3(sig) => verify_detached_signature(sig, challenge, pubkey)
.map_err(|_| Error::InvalidSignature),
_ => Err(Error::UnsupportedAlgorithm)
}
}
}
}
pub enum AnyKeypair {
Ed25519(Box<Ed25519Keypair>),
Dilithium3(Box<Dilithium3Pubkey>, Box<Dilithium3Seckey>)
}
impl AnyKeypair {
pub fn new(name: &str, public: &[u8], secret: &[u8]) -> Result<Self> {
Ok(match name {
"ed25519" => Self::Ed25519(Box::new(Ed25519Keypair {
public: Ed25519Pubkey::from_bytes(public)
.map_err(|_| Error::InvalidData)?,
secret: Ed25519Seckey::from_bytes(secret)
.map_err(|_| Error::InvalidData)?
})),
"dilithium3" => Self::Dilithium3(
Box::new(Dilithium3Pubkey::from_bytes(public)
.map_err(|_| Error::InvalidData)?),
Box::new(Dilithium3Seckey::from_bytes(secret)
.map_err(|_| Error::InvalidData)?)
),
_ => return Err(Error::UnsupportedAlgorithm)
})
}
pub fn generate_ed25519() -> Self {
Self::Ed25519(Box::new(Ed25519Keypair::generate(&mut OsRng)))
}
pub fn generate_dilithium3() -> Self {
let (pk, sk) = keypair();
Self::Dilithium3(Box::new(pk), Box::new(sk))
}
pub fn name(&self) -> &'static str {
match self {
Self::Ed25519(_) => "ed25519",
Self::Dilithium3(_, _) => "dilithium3"
}
}
pub fn public_bytes(&self) -> &[u8] {
match self {
Self::Ed25519(keypair) => keypair.public.as_bytes(),
Self::Dilithium3(pk, _) => pk.as_bytes()
}
}
pub fn secret_bytes(&self) -> &[u8] {
match self {
Self::Ed25519(keypair) => keypair.secret.as_bytes(),
Self::Dilithium3(_, sk) => sk.as_bytes()
}
}
pub fn sign(&self, challenge: &[u8]) -> AnySignature {
match self {
Self::Ed25519(keypair) => AnySignature::Ed25519(keypair.sign(challenge)),
Self::Dilithium3(_, sk) => AnySignature::Dilithium3(Box::new(detached_sign(challenge, sk)))
}
}
}