1use ed25519_dalek::{Signer, SigningKey, VerifyingKey};
8use rand::{TryRng, rngs::SysRng};
9use serde::{Deserialize, Serialize};
10use zeroize::{Zeroize, ZeroizeOnDrop};
11
12use crate::error::{CryptoError, CryptoResult};
13use crate::signature::Signature;
14
15#[derive(ZeroizeOnDrop)]
19pub struct KeyPair {
20 #[zeroize(skip)] verifying_key: VerifyingKey,
22 signing_key: SigningKey,
23}
24
25impl KeyPair {
26 #[must_use]
32 pub fn generate() -> Self {
33 let mut secret = [0u8; 32];
34 SysRng
35 .try_fill_bytes(&mut secret)
36 .expect("OS CSPRNG unavailable while generating key pair");
37 let signing_key = SigningKey::from_bytes(&secret);
38 let verifying_key = signing_key.verifying_key();
39 secret.zeroize();
40 Self {
41 verifying_key,
42 signing_key,
43 }
44 }
45
46 pub fn from_secret_key(bytes: &[u8]) -> CryptoResult<Self> {
52 if bytes.len() != 32 {
53 return Err(CryptoError::InvalidKeyLength {
54 expected: 32,
55 actual: bytes.len(),
56 });
57 }
58
59 let mut secret = [0u8; 32];
60 secret.copy_from_slice(bytes);
61
62 let signing_key = SigningKey::from_bytes(&secret);
63 let verifying_key = signing_key.verifying_key();
64
65 secret.zeroize();
67
68 Ok(Self {
69 verifying_key,
70 signing_key,
71 })
72 }
73
74 #[must_use]
76 pub fn public_key_bytes(&self) -> &[u8; 32] {
77 self.verifying_key.as_bytes()
78 }
79
80 #[must_use]
84 pub fn key_id(&self) -> [u8; 8] {
85 let mut id = [0u8; 8];
86 id.copy_from_slice(&self.public_key_bytes()[..8]);
87 id
88 }
89
90 #[must_use]
92 pub fn key_id_hex(&self) -> String {
93 hex::encode(self.key_id())
94 }
95
96 #[must_use]
98 pub fn sign(&self, message: &[u8]) -> Signature {
99 let sig = self.signing_key.sign(message);
100 Signature::from(sig)
101 }
102
103 pub fn verify(&self, message: &[u8], signature: &Signature) -> CryptoResult<()> {
109 signature.verify(message, self.public_key_bytes())
110 }
111
112 #[must_use]
114 pub fn export_public_key(&self) -> PublicKey {
115 PublicKey::from_bytes(*self.public_key_bytes())
116 }
117
118 #[must_use]
122 pub fn secret_key_bytes(&self) -> [u8; 32] {
123 self.signing_key.to_bytes()
124 }
125}
126
127impl std::fmt::Debug for KeyPair {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 f.debug_struct("KeyPair")
130 .field("key_id", &self.key_id_hex())
131 .finish_non_exhaustive()
132 }
133}
134
135#[derive(Clone, Copy, PartialEq, Eq, Hash)]
137pub struct PublicKey([u8; 32]);
138
139impl PublicKey {
140 #[must_use]
142 pub const fn from_bytes(bytes: [u8; 32]) -> Self {
143 Self(bytes)
144 }
145
146 pub fn try_from_slice(slice: &[u8]) -> CryptoResult<Self> {
152 if slice.len() != 32 {
153 return Err(CryptoError::InvalidKeyLength {
154 expected: 32,
155 actual: slice.len(),
156 });
157 }
158 let mut bytes = [0u8; 32];
159 bytes.copy_from_slice(slice);
160 Ok(Self(bytes))
161 }
162
163 #[must_use]
165 pub const fn as_bytes(&self) -> &[u8; 32] {
166 &self.0
167 }
168
169 #[must_use]
171 pub fn key_id(&self) -> [u8; 8] {
172 let mut id = [0u8; 8];
173 id.copy_from_slice(&self.0[..8]);
174 id
175 }
176
177 #[must_use]
179 pub fn key_id_hex(&self) -> String {
180 hex::encode(self.key_id())
181 }
182
183 #[must_use]
185 pub fn to_hex(&self) -> String {
186 hex::encode(self.0)
187 }
188
189 pub fn from_hex(s: &str) -> CryptoResult<Self> {
195 let bytes = hex::decode(s).map_err(|_| CryptoError::InvalidHexEncoding)?;
196 Self::try_from_slice(&bytes)
197 }
198
199 #[must_use]
201 pub fn to_base64(&self) -> String {
202 use base64::Engine;
203 base64::engine::general_purpose::STANDARD.encode(self.0)
204 }
205
206 pub fn from_base64(s: &str) -> CryptoResult<Self> {
212 use base64::Engine;
213 let bytes = base64::engine::general_purpose::STANDARD
214 .decode(s)
215 .map_err(|_| CryptoError::InvalidBase64Encoding)?;
216 Self::try_from_slice(&bytes)
217 }
218
219 pub fn verify(&self, message: &[u8], signature: &Signature) -> CryptoResult<()> {
225 signature.verify(message, &self.0)
226 }
227}
228
229impl std::fmt::Debug for PublicKey {
230 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231 write!(f, "PublicKey({})", self.key_id_hex())
232 }
233}
234
235impl std::fmt::Display for PublicKey {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 write!(f, "{}", self.to_hex())
238 }
239}
240
241impl Serialize for PublicKey {
242 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243 where
244 S: serde::Serializer,
245 {
246 serializer.serialize_str(&self.to_base64())
247 }
248}
249
250impl<'de> Deserialize<'de> for PublicKey {
251 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
252 where
253 D: serde::Deserializer<'de>,
254 {
255 let s = String::deserialize(deserializer)?;
256 Self::from_base64(&s).map_err(serde::de::Error::custom)
257 }
258}
259
260impl From<[u8; 32]> for PublicKey {
261 fn from(bytes: [u8; 32]) -> Self {
262 Self(bytes)
263 }
264}
265
266impl From<PublicKey> for [u8; 32] {
267 fn from(pk: PublicKey) -> Self {
268 pk.0
269 }
270}
271
272impl AsRef<[u8]> for PublicKey {
273 fn as_ref(&self) -> &[u8] {
274 &self.0
275 }
276}
277
278#[cfg(test)]
279mod tests {
280 use super::*;
281
282 #[test]
283 fn test_keypair_generation() {
284 let kp1 = KeyPair::generate();
285 let kp2 = KeyPair::generate();
286
287 assert_ne!(kp1.public_key_bytes(), kp2.public_key_bytes());
289 }
290
291 #[test]
292 fn test_keypair_from_secret() {
293 let original = KeyPair::generate();
294 let secret = original.secret_key_bytes();
295
296 let restored = KeyPair::from_secret_key(&secret).unwrap();
297
298 assert_eq!(original.public_key_bytes(), restored.public_key_bytes());
299 }
300
301 #[test]
302 fn test_sign_verify() {
303 let keypair = KeyPair::generate();
304 let message = b"hello world";
305
306 let signature = keypair.sign(message);
307 assert!(keypair.verify(message, &signature).is_ok());
308
309 assert!(keypair.verify(b"wrong", &signature).is_err());
311 }
312
313 #[test]
314 fn test_key_id() {
315 let keypair = KeyPair::generate();
316 let key_id = keypair.key_id();
317
318 assert_eq!(&key_id[..], &keypair.public_key_bytes()[..8]);
320
321 let hex_id = keypair.key_id_hex();
323 assert_eq!(hex_id.len(), 16); }
325
326 #[test]
327 fn test_public_key_encoding() {
328 let keypair = KeyPair::generate();
329 let pk = keypair.export_public_key();
330
331 let hex = pk.to_hex();
333 let decoded = PublicKey::from_hex(&hex).unwrap();
334 assert_eq!(pk, decoded);
335
336 let b64 = pk.to_base64();
338 let decoded = PublicKey::from_base64(&b64).unwrap();
339 assert_eq!(pk, decoded);
340 }
341
342 #[test]
343 fn test_public_key_verify() {
344 let keypair = KeyPair::generate();
345 let pk = keypair.export_public_key();
346 let message = b"test";
347
348 let sig = keypair.sign(message);
349 assert!(pk.verify(message, &sig).is_ok());
350 }
351
352 #[test]
353 fn test_invalid_key_length() {
354 let result = KeyPair::from_secret_key(&[0u8; 31]);
355 assert!(matches!(result, Err(CryptoError::InvalidKeyLength { .. })));
356 }
357}