use std::fmt::Debug;
use ed25519_dalek::{Signature, Signer as _, SigningKey, Verifier as _, VerifyingKey};
use crate::core::{Digest, KeyId, Signer, Verifier};
pub struct Ed25519Signer {
key: SigningKey,
key_id: KeyId,
}
impl Debug for Ed25519Signer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Ed25519Signer")
.field("key_id", &self.key_id)
.field("secret", &"<redacted>")
.finish_non_exhaustive()
}
}
impl Ed25519Signer {
#[must_use]
pub fn new(key_id: impl Into<KeyId>, seed: &[u8; 32]) -> Self {
Self {
key: SigningKey::from_bytes(seed),
key_id: key_id.into(),
}
}
#[must_use]
pub fn verifying_key(&self) -> [u8; 32] {
self.key.verifying_key().to_bytes()
}
}
impl Signer for Ed25519Signer {
fn key_id(&self) -> KeyId {
self.key_id.clone()
}
fn sign(&self, hash: &Digest) -> Vec<u8> {
self.key.sign(hash.as_bytes()).to_bytes().to_vec()
}
}
#[derive(Debug, Default)]
pub struct Ed25519Verifier {
keys: std::collections::BTreeMap<KeyId, VerifyingKey>,
}
impl Ed25519Verifier {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn trust(
mut self,
key_id: impl Into<KeyId>,
public: &[u8; 32],
) -> Result<Self, ed25519_dalek::SignatureError> {
self.keys
.insert(key_id.into(), VerifyingKey::from_bytes(public)?);
Ok(self)
}
}
impl Verifier for Ed25519Verifier {
fn verify(&self, key_id: &str, hash: &Digest, signature: &[u8]) -> bool {
let Some(key) = self.keys.get(key_id) else {
return false;
};
let Ok(bytes) = <[u8; 64]>::try_from(signature) else {
return false;
};
key.verify(hash.as_bytes(), &Signature::from_bytes(&bytes))
.is_ok()
}
}
#[cfg(feature = "manifest")]
impl crate::peers::CardSigner for Ed25519Signer {
fn key_id(&self) -> KeyId {
self.key_id.clone()
}
fn sign_bytes(&self, message: &[u8]) -> Vec<u8> {
self.key.sign(message).to_bytes().to_vec()
}
}
#[cfg(feature = "manifest")]
impl crate::peers::CardVerifier for Ed25519Verifier {
fn verify_bytes(&self, key_id: &str, message: &[u8], signature: &[u8]) -> bool {
let Some(key) = self.keys.get(key_id) else {
return false;
};
let Ok(bytes) = <[u8; 64]>::try_from(signature) else {
return false;
};
key.verify(message, &Signature::from_bytes(&bytes)).is_ok()
}
}