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 nested_enum_utils::common_fields;
15use rand_core::CryptoRng;
16use serde::{Deserialize, Serialize};
17use snafu::{Backtrace, Snafu};
18
19#[derive(Clone, Copy, PartialEq, Eq)]
24#[repr(transparent)]
25pub struct PublicKey(CompressedEdwardsY);
26
27impl Borrow<[u8; 32]> for PublicKey {
28 fn borrow(&self) -> &[u8; 32] {
29 self.as_bytes()
30 }
31}
32
33impl Deref for PublicKey {
34 type Target = [u8; 32];
35
36 fn deref(&self) -> &Self::Target {
37 self.as_bytes()
38 }
39}
40
41impl PartialOrd for PublicKey {
42 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
43 Some(self.cmp(other))
44 }
45}
46
47impl Ord for PublicKey {
48 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
49 self.0.as_bytes().cmp(other.0.as_bytes())
50 }
51}
52
53pub type EndpointId = PublicKey;
66
67impl Hash for PublicKey {
68 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
69 self.0.hash(state);
70 }
71}
72
73impl Serialize for PublicKey {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::Serializer,
77 {
78 if serializer.is_human_readable() {
79 serializer.serialize_str(&self.to_string())
80 } else {
81 self.0.as_bytes().serialize(serializer)
82 }
83 }
84}
85
86impl<'de> Deserialize<'de> for PublicKey {
87 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88 where
89 D: serde::Deserializer<'de>,
90 {
91 if deserializer.is_human_readable() {
92 let s = String::deserialize(deserializer)?;
93 Self::from_str(&s).map_err(serde::de::Error::custom)
94 } else {
95 let data: [u8; 32] = serde::Deserialize::deserialize(deserializer)?;
96 Self::try_from(data.as_ref()).map_err(serde::de::Error::custom)
97 }
98 }
99}
100
101impl PublicKey {
102 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
104
105 pub fn as_bytes(&self) -> &[u8; 32] {
107 self.0.as_bytes()
108 }
109
110 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, KeyParsingError> {
118 let key = VerifyingKey::from_bytes(bytes)?;
119 let y = CompressedEdwardsY(key.to_bytes());
120 Ok(Self(y))
121 }
122
123 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
129 self.as_verifying_key()
130 .verify_strict(message, &signature.0)
131 .map_err(|_| SignatureSnafu.build())
132 }
133
134 pub fn fmt_short(&self) -> impl Display + 'static {
137 PublicKeyShort(
138 self.0.as_bytes()[0..5]
139 .try_into()
140 .expect("slice with incorrect length"),
141 )
142 }
143
144 #[doc(hidden)]
146 pub fn as_verifying_key(&self) -> VerifyingKey {
147 VerifyingKey::from_bytes(self.0.as_bytes()).expect("already verified")
148 }
149
150 #[doc(hidden)]
152 pub fn from_verifying_key(key: VerifyingKey) -> Self {
153 Self(CompressedEdwardsY(key.to_bytes()))
154 }
155}
156
157struct PublicKeyShort([u8; 5]);
158
159impl Display for PublicKeyShort {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 data_encoding::HEXLOWER.encode_write(&self.0, f)
162 }
163}
164
165impl TryFrom<&[u8]> for PublicKey {
166 type Error = KeyParsingError;
167
168 #[inline]
169 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
170 let vk = VerifyingKey::try_from(bytes)?;
171 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
172 }
173}
174
175impl TryFrom<&[u8; 32]> for PublicKey {
176 type Error = KeyParsingError;
177
178 #[inline]
179 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
180 Self::from_bytes(bytes)
181 }
182}
183
184impl AsRef<[u8]> for PublicKey {
185 fn as_ref(&self) -> &[u8] {
186 self.as_bytes()
187 }
188}
189
190impl Debug for PublicKey {
191 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192 write!(
193 f,
194 "PublicKey({})",
195 data_encoding::HEXLOWER.encode(self.as_bytes())
196 )
197 }
198}
199
200impl Display for PublicKey {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 write!(f, "{}", data_encoding::HEXLOWER.encode(self.as_bytes()))
203 }
204}
205
206#[common_fields({
208 backtrace: Option<Backtrace>,
209 #[snafu(implicit)]
210 span_trace: n0_snafu::SpanTrace,
211})]
212#[derive(Snafu, Debug)]
213#[allow(missing_docs)]
214#[snafu(visibility(pub(crate)))]
215pub enum KeyParsingError {
216 #[snafu(transparent)]
218 Decode { source: data_encoding::DecodeError },
219 #[snafu(transparent)]
221 Key {
222 source: ed25519_dalek::SignatureError,
223 },
224 #[snafu(display("invalid length"))]
226 DecodeInvalidLength {},
227}
228
229impl FromStr for PublicKey {
233 type Err = KeyParsingError;
234
235 fn from_str(s: &str) -> Result<Self, Self::Err> {
236 let bytes = decode_base32_hex(s)?;
237
238 Self::from_bytes(&bytes)
239 }
240}
241
242#[derive(Clone, zeroize::ZeroizeOnDrop)]
244pub struct SecretKey(SigningKey);
245
246impl Debug for SecretKey {
247 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
248 write!(f, "SecretKey(..)")
249 }
250}
251
252impl FromStr for SecretKey {
253 type Err = KeyParsingError;
254
255 fn from_str(s: &str) -> Result<Self, Self::Err> {
256 let bytes = decode_base32_hex(s)?;
257 Ok(SecretKey::from(bytes))
258 }
259}
260
261impl Serialize for SecretKey {
262 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
263 where
264 S: serde::Serializer,
265 {
266 self.0.serialize(serializer)
267 }
268}
269
270impl<'de> Deserialize<'de> for SecretKey {
271 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
272 where
273 D: serde::Deserializer<'de>,
274 {
275 let secret = SigningKey::deserialize(deserializer)?;
276 Ok(Self(secret))
277 }
278}
279
280impl SecretKey {
281 pub fn public(&self) -> PublicKey {
283 let key = self.0.verifying_key().to_bytes();
284 PublicKey(CompressedEdwardsY(key))
285 }
286
287 pub fn generate<R: CryptoRng + ?Sized>(csprng: &mut R) -> Self {
294 let secret = SigningKey::generate(csprng);
295 Self(secret)
296 }
297
298 pub fn sign(&self, msg: &[u8]) -> Signature {
300 use ed25519_dalek::Signer;
301
302 let sig = self.0.sign(msg);
303 Signature(sig)
304 }
305
306 pub fn to_bytes(&self) -> [u8; 32] {
309 self.0.to_bytes()
310 }
311
312 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
314 let secret = SigningKey::from_bytes(bytes);
315 Self(secret)
316 }
317
318 #[doc(hidden)]
320 pub fn as_signing_key(&self) -> &SigningKey {
321 &self.0
322 }
323}
324
325impl From<[u8; 32]> for SecretKey {
326 fn from(value: [u8; 32]) -> Self {
327 Self::from_bytes(&value)
328 }
329}
330
331impl TryFrom<&[u8]> for SecretKey {
332 type Error = KeyParsingError;
333
334 #[inline]
335 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
336 let secret = SigningKey::try_from(bytes)?;
337 Ok(Self(secret))
338 }
339}
340
341#[derive(Copy, Clone, Eq, PartialEq)]
343pub struct Signature(ed25519_dalek::Signature);
344
345impl Debug for Signature {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 write!(f, "{:?}", self.0)
348 }
349}
350
351impl Display for Signature {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 write!(f, "{}", self.0)
354 }
355}
356
357impl Signature {
358 pub const LENGTH: usize = ed25519_dalek::Signature::BYTE_SIZE;
360
361 pub fn to_bytes(&self) -> [u8; Self::LENGTH] {
363 self.0.to_bytes()
364 }
365
366 pub fn from_bytes(bytes: &[u8; Self::LENGTH]) -> Self {
368 Self(ed25519_dalek::Signature::from_bytes(bytes))
369 }
370}
371
372#[derive(Debug, Snafu)]
374#[snafu(display("Invalid signature"))]
375pub struct SignatureError;
376
377fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
378 let mut bytes = [0u8; 32];
379
380 let res = if s.len() == PublicKey::LENGTH * 2 {
381 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
383 } else {
384 let input = s.to_ascii_uppercase();
385 let input = input.as_bytes();
386 if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() {
387 return Err(DecodeInvalidLengthSnafu.build());
388 }
389 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
390 };
391 match res {
392 Ok(len) => {
393 if len != PublicKey::LENGTH {
394 return Err(DecodeInvalidLengthSnafu.build());
395 }
396 }
397 Err(partial) => return Err(partial.error.into()),
398 }
399 Ok(bytes)
400}
401
402#[cfg(test)]
403mod tests {
404 use data_encoding::HEXLOWER;
405 use rand::SeedableRng;
406
407 use super::*;
408
409 #[test]
410 fn test_public_key_postcard() {
411 let public_key =
412 PublicKey::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
413 .unwrap();
414 let bytes = postcard::to_stdvec(&public_key).unwrap();
415 let expected = HEXLOWER
416 .decode(b"ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
417 .unwrap();
418 assert_eq!(bytes, expected);
419 }
420
421 #[test]
422 fn public_key_postcard() {
423 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
424 let bytes = postcard::to_stdvec(&key).unwrap();
425 let key2: PublicKey = postcard::from_bytes(&bytes).unwrap();
426 assert_eq!(key, key2);
427 }
428
429 #[test]
430 fn public_key_json() {
431 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
432 let bytes = serde_json::to_string(&key).unwrap();
433 let key2: PublicKey = serde_json::from_str(&bytes).unwrap();
434 assert_eq!(key, key2);
435 }
436
437 #[test]
438 fn test_from_str() {
439 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64);
440 let key = SecretKey::generate(&mut rng);
441 assert_eq!(
442 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
443 .unwrap()
444 .to_bytes(),
445 key.to_bytes()
446 );
447
448 assert_eq!(
449 PublicKey::from_str(&key.public().to_string()).unwrap(),
450 key.public()
451 );
452 }
453
454 #[test]
455 fn test_regression_parse_endpoint_id_panic() {
456 let not_a_endpoint_id = "foobarbaz";
457 assert!(PublicKey::from_str(not_a_endpoint_id).is_err());
458 }
459}