use ed25519_dalek::{Signature, Signer as DalekSigner, SigningKey, VerifyingKey};
use rand::rngs::OsRng;
use zeroize::ZeroizeOnDrop;
pub trait Signer: Send + Sync {
fn verifying_key(&self) -> VerifyingKey;
fn sign_message(&self, msg: &[u8]) -> Signature;
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
#[async_trait::async_trait]
pub trait AsyncSigner: Send + Sync {
fn verifying_key(&self) -> VerifyingKey;
async fn sign_message(&self, msg: &[u8]) -> Signature;
}
#[derive(ZeroizeOnDrop)]
pub struct DyoloIdentity {
signing_key: SigningKey,
}
impl DyoloIdentity {
pub fn generate() -> Self {
Self {
signing_key: SigningKey::generate(&mut OsRng),
}
}
pub fn from_signing_bytes(bytes: &[u8; 32]) -> Self {
Self {
signing_key: SigningKey::from_bytes(bytes),
}
}
pub fn to_signing_bytes(&self) -> [u8; 32] {
self.signing_key.to_bytes()
}
pub fn verifying_key(&self) -> VerifyingKey {
self.signing_key.verifying_key()
}
#[allow(dead_code)]
pub(crate) fn sign(&self, message: &[u8]) -> Signature {
self.signing_key.sign(message)
}
}
impl Signer for DyoloIdentity {
fn verifying_key(&self) -> VerifyingKey {
self.signing_key.verifying_key()
}
fn sign_message(&self, msg: &[u8]) -> Signature {
self.signing_key.sign(msg)
}
}
impl std::fmt::Debug for DyoloIdentity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let vk = self.verifying_key();
let b = vk.as_bytes();
write!(
f,
"DyoloIdentity(vk:{:02x}{:02x}{:02x}{:02x}…)",
b[0], b[1], b[2], b[3]
)
}
}
#[derive(Clone, Debug)]
pub struct SharedIdentity(pub std::sync::Arc<DyoloIdentity>);
impl Signer for SharedIdentity {
fn verifying_key(&self) -> VerifyingKey {
self.0.verifying_key()
}
fn sign_message(&self, msg: &[u8]) -> Signature {
Signer::sign_message(&*self.0, msg)
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl AsyncSigner for SharedIdentity {
fn verifying_key(&self) -> VerifyingKey {
self.0.verifying_key()
}
async fn sign_message(&self, msg: &[u8]) -> Signature {
Signer::sign_message(&*self.0, msg)
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl AsyncSigner for DyoloIdentity {
fn verifying_key(&self) -> VerifyingKey {
self.verifying_key()
}
async fn sign_message(&self, msg: &[u8]) -> Signature {
Signer::sign_message(self, msg)
}
}