use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
#[derive(Clone)]
pub struct Ed25519Signer {
key: SigningKey,
}
impl Ed25519Signer {
pub fn from_seed(seed: &[u8; 32]) -> Self {
Self {
key: SigningKey::from_bytes(seed),
}
}
pub fn from_secret_key(key: SigningKey) -> Self {
Self { key }
}
pub fn sign(&self, message: &[u8]) -> [u8; 64] {
self.key.sign(message).to_bytes()
}
pub fn verify(&self, message: &[u8], signature: &[u8; 64]) -> bool {
let sig = Signature::from_bytes(signature);
self.key.verify(message, &sig).is_ok()
}
pub fn verify_with_pubkey(pubkey: &[u8; 32], message: &[u8], signature: &[u8; 64]) -> bool {
let Ok(vk) = VerifyingKey::from_bytes(pubkey) else {
return false;
};
let sig = Signature::from_bytes(signature);
vk.verify(message, &sig).is_ok()
}
pub fn public_key(&self) -> [u8; 32] {
self.key.verifying_key().to_bytes()
}
pub fn secret_key(&self) -> [u8; 32] {
self.key.to_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sign_verify_roundtrip() {
let s = Ed25519Signer::from_seed(&[1u8; 32]);
let msg = b"hello";
let sig = s.sign(msg);
assert!(s.verify(msg, &sig));
}
#[test]
fn verify_rejects_tampered_msg() {
let s = Ed25519Signer::from_seed(&[1u8; 32]);
let sig = s.sign(b"original");
assert!(!s.verify(b"tampered", &sig));
}
#[test]
fn verify_with_pubkey() {
let s = Ed25519Signer::from_seed(&[2u8; 32]);
let pubkey = s.public_key();
let sig = s.sign(b"x");
assert!(Ed25519Signer::verify_with_pubkey(&pubkey, b"x", &sig));
}
}