origin_crypto_sdk/pqc/
ed448.rs1use ed448_goldilocks::Signature as InnerSignature;
45use ed448_goldilocks::SigningKey as InnerSigningKey;
46use ed448_goldilocks::VerifyingKey as InnerVerifyingKey;
47
48use crate::error::{CryptoError, Result};
49
50pub const SECRET_KEY_SIZE: usize = 57;
52
53pub const PUBLIC_KEY_SIZE: usize = 57;
55
56pub const SIGNATURE_SIZE: usize = 114;
58
59#[derive(Clone)]
65pub struct SigningKey(InnerSigningKey);
66
67impl SigningKey {
68 pub fn from_bytes(bytes: &[u8; SECRET_KEY_SIZE]) -> Result<Self> {
70 InnerSigningKey::try_from(bytes.as_slice())
71 .map(SigningKey)
72 .map_err(|e| CryptoError::InvalidKey(format!("invalid Ed448 secret key: {e}")))
73 }
74
75 pub fn sign(&self, message: &[u8]) -> Signature {
80 Signature(self.0.sign_raw(message))
81 }
82
83 pub fn verifying_key(&self) -> VerifyingKey {
85 VerifyingKey(self.0.verifying_key())
86 }
87
88 pub fn to_bytes(&self) -> [u8; SECRET_KEY_SIZE] {
90 let mut out = [0u8; SECRET_KEY_SIZE];
91 out.copy_from_slice(&self.0.to_bytes()[..]);
92 out
93 }
94}
95
96impl Drop for SigningKey {
97 fn drop(&mut self) {
98 }
100}
101
102impl std::fmt::Debug for SigningKey {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("SigningKey")
105 .field("public_key", &hex::encode(self.verifying_key().to_bytes()))
106 .finish_non_exhaustive()
107 }
108}
109
110pub struct VerifyingKey(InnerVerifyingKey);
112
113impl Clone for VerifyingKey {
114 fn clone(&self) -> Self {
115 Self(self.0)
116 }
117}
118
119impl std::fmt::Debug for VerifyingKey {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 f.debug_struct("VerifyingKey")
122 .field("bytes", &hex::encode(self.0.to_bytes()))
123 .finish()
124 }
125}
126
127impl VerifyingKey {
128 pub fn from_bytes(bytes: &[u8; PUBLIC_KEY_SIZE]) -> Result<Self> {
130 InnerVerifyingKey::from_bytes(bytes)
131 .map(VerifyingKey)
132 .map_err(|e| CryptoError::InvalidKey(format!("invalid Ed448 public key: {e}")))
133 }
134
135 pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_SIZE] {
137 self.0.to_bytes()
138 }
139
140 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<()> {
146 self.0
147 .verify_raw(&signature.0, message)
148 .map_err(|_| CryptoError::AuthenticationFailed)
149 }
150}
151
152pub struct Signature(InnerSignature);
157
158impl Signature {
159 pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] {
161 self.0.to_bytes()
162 }
163
164 pub fn from_bytes(bytes: &[u8; SIGNATURE_SIZE]) -> Result<Self> {
166 InnerSignature::try_from(bytes.as_slice())
167 .map(Signature)
168 .map_err(|e| CryptoError::InvalidParameter(format!("invalid Ed448 signature: {e}")))
169 }
170}
171
172impl Clone for Signature {
173 fn clone(&self) -> Self {
174 Self(self.0)
175 }
176}
177
178impl std::fmt::Debug for Signature {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 f.debug_struct("Signature")
181 .field("bytes", &hex::encode(self.to_bytes()))
182 .finish()
183 }
184}
185
186const _: () = {
188 assert!(SECRET_KEY_SIZE == 57);
189 assert!(PUBLIC_KEY_SIZE == 57);
190 assert!(SIGNATURE_SIZE == 114);
191};
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn key_sizes() {
199 assert_eq!(SECRET_KEY_SIZE, 57);
200 assert_eq!(PUBLIC_KEY_SIZE, 57);
201 assert_eq!(SIGNATURE_SIZE, 114);
202 }
203
204 fn sk(seed_byte: u8) -> SigningKey {
205 let seed = [seed_byte; SECRET_KEY_SIZE];
206 SigningKey::from_bytes(&seed).expect("test seed must be valid")
207 }
208
209 #[test]
210 fn sign_verify_roundtrip() {
211 let sk = sk(0x42);
212 let pk = sk.verifying_key();
213 let msg = b"hello Ed448";
214 let sig = sk.sign(msg);
215 assert!(pk.verify(msg, &sig).is_ok());
216 }
217
218 #[test]
219 fn verify_rejects_tampered_message() {
220 let sk = sk(0x42);
221 let pk = sk.verifying_key();
222 let sig = sk.sign(b"original");
223 assert!(pk.verify(b"tampered", &sig).is_err());
224 }
225
226 #[test]
227 fn verify_rejects_tampered_signature() {
228 let sk = sk(0x42);
229 let pk = sk.verifying_key();
230 let mut sig = sk.sign(b"x");
231 let mut bytes = sig.to_bytes();
232 bytes[10] ^= 0x01;
233 let bad_sig = Signature::from_bytes(&bytes).unwrap();
234 assert!(pk.verify(b"x", &bad_sig).is_err());
235 }
236
237 #[test]
238 fn deterministic_signatures() {
239 let sk1 = sk(0x42);
242 let sk2 = sk(0x42);
243 let msg = b"deterministic test";
244 let sig1 = sk1.sign(msg);
245 let sig2 = sk2.sign(msg);
246 assert_eq!(sig1.to_bytes(), sig2.to_bytes());
247 }
248
249 #[test]
250 fn public_key_derivation() {
251 let sk = sk(0x42);
252 let pk = sk.verifying_key();
253 let bytes = pk.to_bytes();
254 let restored = VerifyingKey::from_bytes(&bytes).unwrap();
255 assert_eq!(restored.to_bytes(), pk.to_bytes());
256 }
257}