1use std::ops::Deref;
2
3use curve25519_dalek::edwards::CompressedEdwardsY;
4use iroh::{PublicKey as PPublicKey, SecretKey as SSecretKey};
5use serde::{Deserialize, Serialize};
6use x25519_dalek::{PublicKey as X25519PublicKey, StaticSecret};
7
8pub const PRIVATE_KEY_SIZE: usize = 32;
10pub const PUBLIC_KEY_SIZE: usize = 32;
12
13#[derive(Debug, thiserror::Error)]
15pub enum KeyError {
16 #[error("key error: {0}")]
17 Default(#[from] anyhow::Error),
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Copy)]
39pub struct PublicKey(PPublicKey);
40
41impl Deref for PublicKey {
42 type Target = PPublicKey;
43 fn deref(&self) -> &Self::Target {
44 &self.0
45 }
46}
47
48impl From<PPublicKey> for PublicKey {
49 fn from(key: PPublicKey) -> Self {
50 PublicKey(key)
51 }
52}
53
54impl From<PublicKey> for PPublicKey {
55 fn from(key: PublicKey) -> Self {
56 key.0
57 }
58}
59
60impl From<[u8; PUBLIC_KEY_SIZE]> for PublicKey {
61 fn from(bytes: [u8; PUBLIC_KEY_SIZE]) -> Self {
62 PublicKey(PPublicKey::from_bytes(&bytes).expect("valid public key"))
63 }
64}
65
66impl TryFrom<&[u8]> for PublicKey {
67 type Error = KeyError;
68 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
69 if bytes.len() != PUBLIC_KEY_SIZE {
70 return Err(anyhow::anyhow!(
71 "invalid public key size, expected {}, got {}",
72 PUBLIC_KEY_SIZE,
73 bytes.len()
74 )
75 .into());
76 }
77 let mut buff = [0; PUBLIC_KEY_SIZE];
78 buff.copy_from_slice(bytes);
79 Ok(buff.into())
80 }
81}
82
83impl PublicKey {
84 pub fn from_hex(hex: &str) -> Result<Self, KeyError> {
88 let hex = hex.strip_prefix("0x").unwrap_or(hex);
89 let mut buff = [0; PUBLIC_KEY_SIZE];
90 hex::decode_to_slice(hex, &mut buff)
91 .map_err(|_| anyhow::anyhow!("public key hex decode error"))?;
92 Ok(buff.into())
93 }
94
95 pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_SIZE] {
97 *self.0.as_bytes()
98 }
99
100 pub fn to_hex(&self) -> String {
102 hex::encode(self.to_bytes())
103 }
104
105 #[allow(clippy::wrong_self_convention)]
115 pub(crate) fn to_x25519(&self) -> Result<X25519PublicKey, KeyError> {
116 let edwards_bytes = self.to_bytes();
117 let edwards_point = CompressedEdwardsY::from_slice(&edwards_bytes)
118 .map_err(|_| anyhow::anyhow!("public key invalid edwards point"))?
119 .decompress()
120 .ok_or_else(|| anyhow::anyhow!("public key failed to decompress edwards point"))?;
121
122 let montgomery_point = edwards_point.to_montgomery();
123 Ok(X25519PublicKey::from(montgomery_point.to_bytes()))
124 }
125
126 pub fn verify(
134 &self,
135 msg: &[u8],
136 signature: &ed25519_dalek::Signature,
137 ) -> Result<(), ed25519_dalek::SignatureError> {
138 let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(&self.to_bytes())?;
139 verifying_key.verify_strict(msg, signature)
140 }
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct SecretKey(pub SSecretKey);
171
172impl From<[u8; PRIVATE_KEY_SIZE]> for SecretKey {
173 fn from(secret: [u8; PRIVATE_KEY_SIZE]) -> Self {
174 Self(SSecretKey::from_bytes(&secret))
175 }
176}
177
178impl Deref for SecretKey {
179 type Target = SSecretKey;
180 fn deref(&self) -> &Self::Target {
181 &self.0
182 }
183}
184
185impl SecretKey {
186 pub fn from_hex(hex: &str) -> Result<Self, KeyError> {
190 let hex = hex.strip_prefix("0x").unwrap_or(hex);
191 let mut buff = [0; PRIVATE_KEY_SIZE];
192 hex::decode_to_slice(hex, &mut buff)
193 .map_err(|_| anyhow::anyhow!("private key hex decode error"))?;
194 Ok(Self::from(buff))
195 }
196
197 pub fn generate() -> Self {
199 let mut bytes = [0u8; PRIVATE_KEY_SIZE];
200 getrandom::getrandom(&mut bytes).expect("failed to generate random bytes");
201 Self::from(bytes)
202 }
203
204 pub fn public(&self) -> PublicKey {
206 PublicKey(self.0.public())
207 }
208
209 pub fn to_bytes(&self) -> [u8; PRIVATE_KEY_SIZE] {
211 self.0.to_bytes()
212 }
213
214 pub fn to_hex(&self) -> String {
216 hex::encode(self.to_bytes())
217 }
218
219 pub fn to_pem(&self) -> String {
223 let pem = pem::Pem::new("PRIVATE KEY", self.to_bytes());
224 pem::encode(&pem)
225 }
226
227 pub fn from_pem(pem_str: &str) -> Result<Self, KeyError> {
236 let pem = pem::parse(pem_str).map_err(|e| anyhow::anyhow!("failed to parse PEM: {}", e))?;
237
238 if pem.tag() != "PRIVATE KEY" {
239 return Err(anyhow::anyhow!("invalid PEM tag, expected PRIVATE KEY").into());
240 }
241
242 let contents = pem.contents();
243 if contents.len() != PRIVATE_KEY_SIZE {
244 return Err(anyhow::anyhow!(
245 "invalid private key size in PEM, expected {}, got {}",
246 PRIVATE_KEY_SIZE,
247 contents.len()
248 )
249 .into());
250 }
251
252 let mut bytes = [0u8; PRIVATE_KEY_SIZE];
253 bytes.copy_from_slice(contents);
254 Ok(Self::from(bytes))
255 }
256
257 pub(crate) fn to_x25519(&self) -> StaticSecret {
262 let signing_key = self.0.secret();
263 let scalar_bytes = signing_key.to_scalar_bytes();
264 StaticSecret::from(scalar_bytes)
265 }
266
267 pub fn sign(&self, msg: &[u8]) -> ed25519_dalek::Signature {
271 let sig = self.0.sign(msg);
274 ed25519_dalek::Signature::from_bytes(&sig.to_bytes())
275 }
276}
277
278#[cfg(test)]
279mod test {
280 use super::*;
281
282 #[test]
283 fn test_keypair_generation() {
284 let private_key = SecretKey::generate();
285 let public_key = private_key.public();
286
287 let private_hex = private_key.to_hex();
289 let recovered_private = SecretKey::from_hex(&private_hex).unwrap();
290 assert_eq!(private_key.to_bytes(), recovered_private.to_bytes());
291
292 let public_hex = public_key.to_hex();
293 let recovered_public = PublicKey::from_hex(&public_hex).unwrap();
294 assert_eq!(public_key.to_bytes(), recovered_public.to_bytes());
295 }
296
297 #[test]
298 fn test_pem_serialization() {
299 let private_key = SecretKey::generate();
300
301 let pem = private_key.to_pem();
303 let recovered_private = SecretKey::from_pem(&pem).unwrap();
304 assert_eq!(private_key.to_bytes(), recovered_private.to_bytes());
305
306 assert_eq!(
308 private_key.public().to_bytes(),
309 recovered_private.public().to_bytes()
310 );
311 }
312
313 #[test]
314 fn test_sign_and_verify() {
315 let secret_key = SecretKey::generate();
316 let public_key = secret_key.public();
317 let message = b"hello, world!";
318
319 let signature = secret_key.sign(message);
321
322 assert!(public_key.verify(message, &signature).is_ok());
324
325 let wrong_message = b"hello, world?";
327 assert!(public_key.verify(wrong_message, &signature).is_err());
328
329 let other_key = SecretKey::generate().public();
331 assert!(other_key.verify(message, &signature).is_err());
332 }
333}