#![forbid(unsafe_code)]
use core::{
borrow::Borrow,
fmt::{self, Debug},
num::NonZeroU16,
result::Result,
};
use aranya_buggy::Bug;
use crate::{
asn1::EncodingError,
import::Import,
keys::{PublicKey, SecretKey},
AlgId,
};
#[derive(Debug, Eq, PartialEq)]
pub enum SignerError {
Other(&'static str),
Encoding(EncodingError),
Verification,
InvalidBatchLengths,
Bug(Bug),
}
impl fmt::Display for SignerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Other(msg) => write!(f, "{}", msg),
Self::Encoding(err) => write!(f, "{}", err),
Self::Verification => write!(f, "unable to verify signature"),
Self::InvalidBatchLengths => write!(f, "invalid `verify_batch` lengths"),
Self::Bug(err) => write!(f, "{err}"),
}
}
}
impl core::error::Error for SignerError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::Other(_) => None,
Self::Encoding(err) => Some(err),
Self::Verification => None,
Self::InvalidBatchLengths => None,
Self::Bug(err) => Some(err),
}
}
}
impl From<EncodingError> for SignerError {
fn from(err: EncodingError) -> Self {
Self::Encoding(err)
}
}
impl From<Bug> for SignerError {
fn from(err: Bug) -> Self {
Self::Bug(err)
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, AlgId)]
pub enum SignerId {
#[alg_id(0x0001)]
P256,
#[alg_id(0x0002)]
P384,
#[alg_id(0x0003)]
P521,
#[alg_id(0x0004)]
Ed25519,
#[alg_id(0x0005)]
Ed448,
#[alg_id(Other)]
Other(NonZeroU16),
}
pub trait Signer {
const ID: SignerId;
type SigningKey: SigningKey<Self>;
type VerifyingKey: VerifyingKey<Self>;
type Signature: Signature<Self>;
fn verify_batch(
msgs: &[&[u8]],
sigs: &[Self::Signature],
pks: &[Self::VerifyingKey],
) -> Result<(), SignerError> {
if msgs.len() != sigs.len() || sigs.len() != pks.len() {
return Err(SignerError::InvalidBatchLengths);
}
for (msg, (sig, pk)) in msgs.iter().zip(sigs.iter().zip(pks)) {
pk.verify(msg, sig)?;
}
Ok(())
}
}
pub trait SigningKey<T: Signer + ?Sized>: SecretKey {
fn sign(&self, msg: &[u8]) -> Result<T::Signature, SignerError>;
fn public(&self) -> Result<T::VerifyingKey, PkError>;
}
#[derive(Debug, Eq, PartialEq)]
pub struct PkError(pub(crate) &'static str);
impl fmt::Display for PkError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl core::error::Error for PkError {}
pub trait VerifyingKey<T: Signer + ?Sized>: PublicKey {
fn verify(&self, msg: &[u8], sig: &T::Signature) -> Result<(), SignerError>;
}
pub trait Signature<T: Signer + ?Sized>: Clone + Debug + for<'a> Import<&'a [u8]> {
type Data: Borrow<[u8]> + Clone + Sized;
fn export(&self) -> Self::Data;
}