encryption/asymmetric/
ed25519.rs1use ed25519_dalek::{Signature, Signer as _, SigningKey, VerifyingKey};
16use rand_core::OsRng;
17
18use crate::asymmetric::KeyPairHex;
19use crate::contract::{Identified, Signer};
20use crate::error::{Error, Result};
21use crate::internal::{hex_decode, hex_encode};
22
23const LABEL: &str = "Ed25519";
24
25#[derive(Debug, Default, Clone, Copy)]
27pub struct Ed25519Signer;
28
29impl Ed25519Signer {
30 pub const IDENTIFIER: &'static str = "ed25519";
31
32 pub fn new() -> Self {
33 Self
34 }
35
36 fn sign_hex(message: &[u8], private_key_hex: &str) -> Result<String> {
38 let seed =
39 parse_32_bytes(private_key_hex).map_err(|_| Error::InvalidKey { label: LABEL })?;
40 let signing_key = SigningKey::from_bytes(&seed);
41 Ok(hex_encode(&signing_key.sign(message).to_bytes()))
42 }
43
44 fn verify_hex(message: &[u8], signature_hex: &str, public_key_hex: &str) -> Result<()> {
46 let public_bytes = parse_32_bytes(public_key_hex)
47 .map_err(|_| Error::VerificationFailed { label: LABEL })?;
48 let verifying_key = VerifyingKey::from_bytes(&public_bytes)
49 .map_err(|_| Error::VerificationFailed { label: LABEL })?;
50 let signature_bytes =
51 hex_decode(signature_hex).map_err(|_| Error::VerificationFailed { label: LABEL })?;
52 let signature = Signature::from_slice(&signature_bytes)
53 .map_err(|_| Error::VerificationFailed { label: LABEL })?;
54 verifying_key
55 .verify_strict(message, &signature)
56 .map_err(|_| Error::VerificationFailed { label: LABEL })
57 }
58
59 pub fn generate_key_pair_hex() -> Result<KeyPairHex> {
61 let signing_key = SigningKey::generate(&mut OsRng);
62 Ok(KeyPairHex {
63 private_key_hex: hex_encode(&signing_key.to_bytes()),
64 public_key_hex: hex_encode(signing_key.verifying_key().as_bytes()),
65 })
66 }
67}
68
69fn parse_32_bytes(hex: &str) -> Result<[u8; 32]> {
71 hex_decode(hex)?.try_into().map_err(|_| Error::InvalidHex)
72}
73
74impl Identified for Ed25519Signer {
75 fn identifier(&self) -> &str {
76 Self::IDENTIFIER
77 }
78}
79
80impl Signer for Ed25519Signer {
81 fn sign(&self, message: &[u8], private_key_hex: &str) -> Result<String> {
82 Self::sign_hex(message, private_key_hex)
83 }
84
85 fn verify(&self, message: &[u8], signature_hex: &str, public_key_hex: &str) -> Result<()> {
86 Self::verify_hex(message, signature_hex, public_key_hex)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
97 fn small_order_public_key_is_rejected() {
98 const IDENTITY_PK: &str =
99 "0100000000000000000000000000000000000000000000000000000000000000";
100 let signer = Ed25519Signer::new();
101 let dummy_signature = "00".repeat(64);
102 assert_eq!(
103 signer
104 .verify(b"any message", &dummy_signature, IDENTITY_PK)
105 .unwrap_err(),
106 Error::VerificationFailed { label: LABEL }
107 );
108 }
109
110 #[test]
113 fn rfc8032_test1_empty_message() {
114 const SEED: &str = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
115 const PUBLIC_KEY: &str = "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
116 const SIGNATURE: &str = concat!(
117 "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155",
118 "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b",
119 );
120
121 let signer = Ed25519Signer::new();
122 let signature = signer.sign(b"", SEED).unwrap();
123 assert_eq!(signature, SIGNATURE);
124
125 signer.verify(b"", SIGNATURE, PUBLIC_KEY).unwrap();
126 let mut tampered = SIGNATURE.to_string();
128 let last = tampered.len() - 1;
129 let flipped = if tampered.as_bytes()[last] == b'0' {
130 '1'
131 } else {
132 '0'
133 };
134 tampered.replace_range(last.., &flipped.to_string());
135 assert!(signer.verify(b"", &tampered, PUBLIC_KEY).is_err());
136 }
137
138 #[test]
140 fn rfc8032_test3_two_byte_message() {
141 const SEED: &str = "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7";
142 const PUBLIC_KEY: &str = "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025";
143 const SIGNATURE: &str = concat!(
144 "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac",
145 "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a",
146 );
147 let message = hex_decode("af82").unwrap();
148
149 let signer = Ed25519Signer::new();
150 assert_eq!(signer.sign(&message, SEED).unwrap(), SIGNATURE);
151 signer.verify(&message, SIGNATURE, PUBLIC_KEY).unwrap();
152 assert!(signer.verify(b"af83", SIGNATURE, PUBLIC_KEY).is_err());
154 }
155
156 #[test]
157 fn keypair_roundtrip_and_hex_shapes() {
158 let pair = Ed25519Signer::generate_key_pair_hex().unwrap();
159 assert_eq!(pair.private_key_hex.len(), 64);
160 assert_eq!(pair.public_key_hex.len(), 64);
161
162 let signer = Ed25519Signer::new();
163 let message = "非 ASCII 消息 🎉".as_bytes();
164 let signature = signer.sign(message, &pair.private_key_hex).unwrap();
165 assert_eq!(signature.len(), 128);
166 signer
167 .verify(message, &signature, &pair.public_key_hex)
168 .unwrap();
169
170 let other = Ed25519Signer::generate_key_pair_hex().unwrap();
172 assert!(
173 signer
174 .verify(message, &signature, &other.public_key_hex)
175 .is_err()
176 );
177 assert!(
178 signer
179 .verify(b"changed", &signature, &pair.public_key_hex)
180 .is_err()
181 );
182 }
183
184 #[test]
185 fn signatures_are_deterministic() {
186 let pair = Ed25519Signer::generate_key_pair_hex().unwrap();
187 let signer = Ed25519Signer::new();
188 assert_eq!(
189 signer.sign(b"same", &pair.private_key_hex).unwrap(),
190 signer.sign(b"same", &pair.private_key_hex).unwrap(),
191 );
192 }
193
194 #[test]
195 fn malformed_keys_are_rejected() {
196 let pair = Ed25519Signer::generate_key_pair_hex().unwrap();
197 let signer = Ed25519Signer::new();
198
199 assert_eq!(
200 signer.sign(b"x", "zz").unwrap_err(),
201 Error::InvalidKey { label: LABEL }
202 );
203 assert_eq!(
205 signer.sign(b"x", &pair.private_key_hex[..62]).unwrap_err(),
206 Error::InvalidKey { label: LABEL }
207 );
208 assert_eq!(
209 signer.verify(b"x", "00", &pair.public_key_hex).unwrap_err(),
210 Error::VerificationFailed { label: LABEL }
211 );
212 assert_eq!(
213 signer
214 .verify(b"x", "00", &pair.public_key_hex[..62])
215 .unwrap_err(),
216 Error::VerificationFailed { label: LABEL }
217 );
218 }
219
220 #[test]
221 fn identifier_is_stable() {
222 assert_eq!(Ed25519Signer::new().identifier(), "ed25519");
223 }
224}