origin_crypto_sdk/signing/
classical.rs1use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
22
23#[derive(Clone)]
28pub struct Ed25519Signer {
29 key: SigningKey,
30}
31
32impl std::fmt::Debug for Ed25519Signer {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("Ed25519Signer").finish_non_exhaustive()
36 }
37}
38
39impl Ed25519Signer {
40 pub fn from_seed(seed: &[u8; 32]) -> Self {
42 Self {
43 key: SigningKey::from_bytes(seed),
44 }
45 }
46
47 pub fn from_secret_key(key: SigningKey) -> Self {
49 Self { key }
50 }
51
52 pub fn sign(&self, message: &[u8]) -> [u8; 64] {
54 self.key.sign(message).to_bytes()
55 }
56
57 pub fn verify(&self, message: &[u8], signature: &[u8; 64]) -> bool {
59 let sig = Signature::from_bytes(signature);
60 self.key.verify(message, &sig).is_ok()
61 }
62
63 pub fn verify_with_pubkey(pubkey: &[u8; 32], message: &[u8], signature: &[u8; 64]) -> bool {
65 let Ok(vk) = VerifyingKey::from_bytes(pubkey) else {
66 return false;
67 };
68 let sig = Signature::from_bytes(signature);
69 vk.verify(message, &sig).is_ok()
70 }
71
72 pub fn public_key(&self) -> [u8; 32] {
74 self.key.verifying_key().to_bytes()
75 }
76
77 pub fn secret_key(&self) -> [u8; 32] {
79 self.key.to_bytes()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn sign_verify_roundtrip() {
89 let s = Ed25519Signer::from_seed(&[1u8; 32]);
90 let msg = b"hello";
91 let sig = s.sign(msg);
92 assert!(s.verify(msg, &sig));
93 }
94
95 #[test]
96 fn verify_rejects_tampered_msg() {
97 let s = Ed25519Signer::from_seed(&[1u8; 32]);
98 let sig = s.sign(b"original");
99 assert!(!s.verify(b"tampered", &sig));
100 }
101
102 #[test]
103 fn verify_with_pubkey() {
104 let s = Ed25519Signer::from_seed(&[2u8; 32]);
105 let pubkey = s.public_key();
106 let sig = s.sign(b"x");
107 assert!(Ed25519Signer::verify_with_pubkey(&pubkey, b"x", &sig));
108 }
109}