1use std::{
4 borrow::Borrow,
5 cmp::{Ord, PartialOrd},
6 fmt::{self, Debug, Display},
7 hash::Hash,
8 ops::Deref,
9 str::FromStr,
10};
11
12use curve25519_dalek::edwards::CompressedEdwardsY;
13use ed25519_dalek::{SigningKey, VerifyingKey};
14use n0_error::{ensure, stack_error};
15use rand_core::CryptoRng;
16use serde::{Deserialize, Serialize, de, ser};
17
18#[derive(Clone, Copy, PartialEq, Eq)]
23#[repr(transparent)]
24pub struct PublicKey(CompressedEdwardsY);
25
26impl Borrow<[u8; 32]> for PublicKey {
27 fn borrow(&self) -> &[u8; 32] {
28 self.as_bytes()
29 }
30}
31
32impl Deref for PublicKey {
33 type Target = [u8; 32];
34
35 fn deref(&self) -> &Self::Target {
36 self.as_bytes()
37 }
38}
39
40impl PartialOrd for PublicKey {
41 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
42 Some(self.cmp(other))
43 }
44}
45
46impl Ord for PublicKey {
47 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
48 self.0.as_bytes().cmp(other.0.as_bytes())
49 }
50}
51
52pub type EndpointId = PublicKey;
65
66impl Hash for PublicKey {
67 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
68 self.0.hash(state);
69 }
70}
71
72impl Serialize for PublicKey {
73 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74 where
75 S: serde::Serializer,
76 {
77 if serializer.is_human_readable() {
78 serializer.serialize_str(&self.to_string())
79 } else {
80 self.0.as_bytes().serialize(serializer)
81 }
82 }
83}
84
85impl<'de> Deserialize<'de> for PublicKey {
86 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87 where
88 D: serde::Deserializer<'de>,
89 {
90 if deserializer.is_human_readable() {
91 let s = String::deserialize(deserializer)?;
92 Self::from_str(&s).map_err(serde::de::Error::custom)
93 } else {
94 let data: [u8; 32] = serde::Deserialize::deserialize(deserializer)?;
95 Self::try_from(data.as_ref()).map_err(serde::de::Error::custom)
96 }
97 }
98}
99
100impl PublicKey {
101 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
103
104 pub fn as_bytes(&self) -> &[u8; 32] {
106 self.0.as_bytes()
107 }
108
109 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, KeyParsingError> {
117 let key = VerifyingKey::from_bytes(bytes)?;
118 let y = CompressedEdwardsY(key.to_bytes());
119 Ok(Self(y))
120 }
121
122 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
128 self.as_verifying_key()
129 .verify_strict(message, &signature.0)
130 .map_err(|_| SignatureError::new())
131 }
132
133 pub fn fmt_short(&self) -> impl Display + 'static {
136 PublicKeyShort(
137 self.0.as_bytes()[0..5]
138 .try_into()
139 .expect("slice with incorrect length"),
140 )
141 }
142
143 #[doc(hidden)]
145 pub fn as_verifying_key(&self) -> VerifyingKey {
146 VerifyingKey::from_bytes(self.0.as_bytes()).expect("already verified")
147 }
148
149 #[doc(hidden)]
151 pub fn from_verifying_key(key: VerifyingKey) -> Self {
152 Self(CompressedEdwardsY(key.to_bytes()))
153 }
154}
155
156struct PublicKeyShort([u8; 5]);
157
158impl Display for PublicKeyShort {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 data_encoding::HEXLOWER.encode_write(&self.0, f)
161 }
162}
163
164impl TryFrom<&[u8]> for PublicKey {
165 type Error = KeyParsingError;
166
167 #[inline]
168 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
169 let vk = VerifyingKey::try_from(bytes)?;
170 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
171 }
172}
173
174impl TryFrom<&[u8; 32]> for PublicKey {
175 type Error = KeyParsingError;
176
177 #[inline]
178 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
179 Self::from_bytes(bytes)
180 }
181}
182
183impl AsRef<[u8]> for PublicKey {
184 fn as_ref(&self) -> &[u8] {
185 self.as_bytes()
186 }
187}
188
189impl Debug for PublicKey {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 write!(
192 f,
193 "PublicKey({})",
194 data_encoding::HEXLOWER.encode(self.as_bytes())
195 )
196 }
197}
198
199impl Display for PublicKey {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "{}", data_encoding::HEXLOWER.encode(self.as_bytes()))
202 }
203}
204
205#[stack_error(derive, add_meta, from_sources, std_sources)]
207#[allow(missing_docs)]
208pub enum KeyParsingError {
209 #[error(transparent)]
211 Decode(data_encoding::DecodeError),
212 #[error(transparent)]
214 Key(ed25519_dalek::SignatureError),
215 #[error("invalid length")]
217 DecodeInvalidLength,
218}
219
220impl FromStr for PublicKey {
224 type Err = KeyParsingError;
225
226 fn from_str(s: &str) -> Result<Self, Self::Err> {
227 let bytes = decode_base32_hex(s)?;
228
229 Self::from_bytes(&bytes)
230 }
231}
232
233#[derive(Clone, zeroize::ZeroizeOnDrop)]
235pub struct SecretKey(SigningKey);
236
237impl Debug for SecretKey {
238 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239 write!(f, "SecretKey(..)")
240 }
241}
242
243impl FromStr for SecretKey {
244 type Err = KeyParsingError;
245
246 fn from_str(s: &str) -> Result<Self, Self::Err> {
247 let bytes = decode_base32_hex(s)?;
248 Ok(SecretKey::from(bytes))
249 }
250}
251
252impl Serialize for SecretKey {
253 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
254 where
255 S: serde::Serializer,
256 {
257 self.0.serialize(serializer)
258 }
259}
260
261impl<'de> Deserialize<'de> for SecretKey {
262 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
263 where
264 D: serde::Deserializer<'de>,
265 {
266 let secret = SigningKey::deserialize(deserializer)?;
267 Ok(Self(secret))
268 }
269}
270
271impl SecretKey {
272 pub fn public(&self) -> PublicKey {
274 let key = self.0.verifying_key().to_bytes();
275 PublicKey(CompressedEdwardsY(key))
276 }
277
278 pub fn generate<R: CryptoRng + ?Sized>(csprng: &mut R) -> Self {
285 let secret = SigningKey::generate(csprng);
286 Self(secret)
287 }
288
289 pub fn sign(&self, msg: &[u8]) -> Signature {
291 use ed25519_dalek::Signer;
292
293 let sig = self.0.sign(msg);
294 Signature(sig)
295 }
296
297 pub fn to_bytes(&self) -> [u8; 32] {
300 self.0.to_bytes()
301 }
302
303 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
305 let secret = SigningKey::from_bytes(bytes);
306 Self(secret)
307 }
308
309 #[doc(hidden)]
311 pub fn as_signing_key(&self) -> &SigningKey {
312 &self.0
313 }
314}
315
316impl From<[u8; 32]> for SecretKey {
317 fn from(value: [u8; 32]) -> Self {
318 Self::from_bytes(&value)
319 }
320}
321
322impl TryFrom<&[u8]> for SecretKey {
323 type Error = KeyParsingError;
324
325 #[inline]
326 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
327 let secret = SigningKey::try_from(bytes)?;
328 Ok(Self(secret))
329 }
330}
331
332#[derive(Copy, Clone, Eq, PartialEq)]
334pub struct Signature(ed25519_dalek::Signature);
335
336impl Serialize for Signature {
337 fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
338 use ser::SerializeTuple;
339
340 let mut seq = serializer.serialize_tuple(Signature::LENGTH)?;
341
342 for byte in self.to_bytes() {
343 seq.serialize_element(&byte)?;
344 }
345
346 seq.end()
347 }
348}
349
350impl<'de> Deserialize<'de> for Signature {
353 fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
354 struct ByteArrayVisitor;
355
356 impl<'de> de::Visitor<'de> for ByteArrayVisitor {
357 type Value = [u8; Signature::LENGTH];
358
359 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
360 formatter.write_str("bytestring of length 64")
361 }
362
363 fn visit_seq<A>(self, mut seq: A) -> Result<[u8; Signature::LENGTH], A::Error>
364 where
365 A: de::SeqAccess<'de>,
366 {
367 use de::Error;
368 let mut arr = [0u8; Signature::LENGTH];
369
370 for (i, byte) in arr.iter_mut().enumerate() {
371 *byte = seq
372 .next_element()?
373 .ok_or_else(|| Error::invalid_length(i, &self))?;
374 }
375
376 Ok(arr)
377 }
378 }
379
380 deserializer
381 .deserialize_tuple(Signature::LENGTH, ByteArrayVisitor)
382 .map(|b| Signature::from_bytes(&b))
383 }
384}
385
386impl Debug for Signature {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 write!(f, "{:?}", self.0)
389 }
390}
391
392impl Display for Signature {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 write!(f, "{}", self.0)
395 }
396}
397
398impl Signature {
399 pub const LENGTH: usize = ed25519_dalek::Signature::BYTE_SIZE;
401
402 pub fn to_bytes(&self) -> [u8; Self::LENGTH] {
404 self.0.to_bytes()
405 }
406
407 pub fn from_bytes(bytes: &[u8; Self::LENGTH]) -> Self {
409 Self(ed25519_dalek::Signature::from_bytes(bytes))
410 }
411}
412
413#[stack_error(derive, add_meta)]
415#[error("Invalid signature")]
416pub struct SignatureError {}
417
418fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
419 let mut bytes = [0u8; 32];
420
421 let res = if s.len() == PublicKey::LENGTH * 2 {
422 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
424 } else {
425 let input = s.to_ascii_uppercase();
426 let input = input.as_bytes();
427 ensure!(
428 data_encoding::BASE32_NOPAD.decode_len(input.len())? == bytes.len(),
429 KeyParsingError::DecodeInvalidLength
430 );
431 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
432 };
433 match res {
434 Ok(len) => {
435 ensure!(
436 len == PublicKey::LENGTH,
437 KeyParsingError::DecodeInvalidLength
438 );
439 }
440 Err(partial) => return Err(partial.error.into()),
441 }
442 Ok(bytes)
443}
444
445#[cfg(test)]
446mod tests {
447 use data_encoding::HEXLOWER;
448 use rand::SeedableRng;
449
450 use super::*;
451
452 #[test]
453 fn test_public_key_postcard() {
454 let public_key =
455 PublicKey::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
456 .unwrap();
457 let bytes = postcard::to_stdvec(&public_key).unwrap();
458 let expected = HEXLOWER
459 .decode(b"ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
460 .unwrap();
461 assert_eq!(bytes, expected);
462 }
463
464 #[test]
465 fn public_key_postcard() {
466 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
467 let bytes = postcard::to_stdvec(&key).unwrap();
468 let key2: PublicKey = postcard::from_bytes(&bytes).unwrap();
469 assert_eq!(key, key2);
470 }
471
472 #[test]
473 fn public_key_json() {
474 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
475 let bytes = serde_json::to_string(&key).unwrap();
476 let key2: PublicKey = serde_json::from_str(&bytes).unwrap();
477 assert_eq!(key, key2);
478 }
479
480 #[test]
481 fn test_from_str() {
482 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64);
483 let key = SecretKey::generate(&mut rng);
484 assert_eq!(
485 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
486 .unwrap()
487 .to_bytes(),
488 key.to_bytes()
489 );
490
491 assert_eq!(
492 PublicKey::from_str(&key.public().to_string()).unwrap(),
493 key.public()
494 );
495 }
496
497 #[test]
498 fn test_regression_parse_endpoint_id_panic() {
499 let not_a_endpoint_id = "foobarbaz";
500 assert!(PublicKey::from_str(not_a_endpoint_id).is_err());
501 }
502
503 #[test]
504 fn signature_postcard() {
505 let key = SecretKey::generate(&mut rand::rng());
506 let signature = key.sign(b"hello world");
507 let bytes = postcard::to_stdvec(&signature).unwrap();
508 let signature2: Signature = postcard::from_bytes(&bytes).unwrap();
509 assert_eq!(signature, signature2);
510 }
511}