1use std::{
4 borrow::Borrow,
5 cmp::{Ord, PartialOrd},
6 fmt::{Debug, Display},
7 hash::Hash,
8 ops::Deref,
9 str::FromStr,
10};
11
12use curve25519_dalek::edwards::CompressedEdwardsY;
13pub use ed25519_dalek::{Signature, SignatureError};
14use ed25519_dalek::{SigningKey, VerifyingKey};
15use nested_enum_utils::common_fields;
16use rand_core::CryptoRngCore;
17use serde::{Deserialize, Serialize};
18use snafu::{Backtrace, Snafu};
19
20#[derive(Clone, Copy, PartialEq, Eq)]
25#[repr(transparent)]
26pub struct PublicKey(CompressedEdwardsY);
27
28impl Borrow<[u8; 32]> for PublicKey {
29 fn borrow(&self) -> &[u8; 32] {
30 self.as_bytes()
31 }
32}
33
34impl Deref for PublicKey {
35 type Target = [u8; 32];
36
37 fn deref(&self) -> &Self::Target {
38 self.as_bytes()
39 }
40}
41
42impl PartialOrd for PublicKey {
43 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
44 Some(self.cmp(other))
45 }
46}
47
48impl Ord for PublicKey {
49 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
50 self.0.as_bytes().cmp(other.0.as_bytes())
51 }
52}
53
54pub type NodeId = PublicKey;
67
68impl Hash for PublicKey {
69 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
70 self.0.hash(state);
71 }
72}
73
74impl Serialize for PublicKey {
75 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76 where
77 S: serde::Serializer,
78 {
79 if serializer.is_human_readable() {
80 serializer.serialize_str(&self.to_string())
81 } else {
82 self.0.as_bytes().serialize(serializer)
83 }
84 }
85}
86
87impl<'de> Deserialize<'de> for PublicKey {
88 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 where
90 D: serde::Deserializer<'de>,
91 {
92 if deserializer.is_human_readable() {
93 let s = String::deserialize(deserializer)?;
94 Self::from_str(&s).map_err(serde::de::Error::custom)
95 } else {
96 let data: [u8; 32] = serde::Deserialize::deserialize(deserializer)?;
97 Self::try_from(data.as_ref()).map_err(serde::de::Error::custom)
98 }
99 }
100}
101
102impl PublicKey {
103 pub fn as_bytes(&self) -> &[u8; 32] {
105 self.0.as_bytes()
106 }
107
108 pub fn public(&self) -> VerifyingKey {
110 VerifyingKey::from_bytes(self.0.as_bytes()).expect("already verified")
111 }
112
113 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
121 let key = VerifyingKey::from_bytes(bytes)?;
122 let y = CompressedEdwardsY(key.to_bytes());
123 Ok(Self(y))
124 }
125
126 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
132 self.public().verify_strict(message, signature)
133 }
134
135 pub fn fmt_short(&self) -> impl Display + 'static {
138 PublicKeyShort(
139 self.0.as_bytes()[0..5]
140 .try_into()
141 .expect("slice with incorrect length"),
142 )
143 }
144
145 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
147}
148
149struct PublicKeyShort([u8; 5]);
150
151impl Display for PublicKeyShort {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 data_encoding::HEXLOWER.encode_write(&self.0, f)
154 }
155}
156
157impl TryFrom<&[u8]> for PublicKey {
158 type Error = SignatureError;
159
160 #[inline]
161 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
162 let vk = VerifyingKey::try_from(bytes)?;
163 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
164 }
165}
166
167impl TryFrom<&[u8; 32]> for PublicKey {
168 type Error = SignatureError;
169
170 #[inline]
171 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
172 Self::from_bytes(bytes)
173 }
174}
175
176impl AsRef<[u8]> for PublicKey {
177 fn as_ref(&self) -> &[u8] {
178 self.as_bytes()
179 }
180}
181
182impl From<VerifyingKey> for PublicKey {
183 fn from(verifying_key: VerifyingKey) -> Self {
184 let key = verifying_key.to_bytes();
185 PublicKey(CompressedEdwardsY(key))
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#[common_fields({
207 backtrace: Option<Backtrace>,
208 #[snafu(implicit)]
209 span_trace: n0_snafu::SpanTrace,
210})]
211#[derive(Snafu, Debug)]
212#[allow(missing_docs)]
213#[snafu(visibility(pub(crate)))]
214pub enum KeyParsingError {
215 #[snafu(transparent)]
217 Decode { source: data_encoding::DecodeError },
218 #[snafu(transparent)]
220 Key {
221 source: ed25519_dalek::SignatureError,
222 },
223 #[snafu(display("invalid length"))]
225 DecodeInvalidLength {},
226}
227
228impl FromStr for PublicKey {
232 type Err = KeyParsingError;
233
234 fn from_str(s: &str) -> Result<Self, Self::Err> {
235 let bytes = decode_base32_hex(s)?;
236
237 Ok(Self::from_bytes(&bytes)?)
238 }
239}
240
241#[derive(Clone)]
243pub struct SecretKey {
244 secret: SigningKey,
245}
246
247impl Debug for SecretKey {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 write!(f, "SecretKey(..)")
250 }
251}
252
253impl FromStr for SecretKey {
254 type Err = KeyParsingError;
255
256 fn from_str(s: &str) -> Result<Self, Self::Err> {
257 let bytes = decode_base32_hex(s)?;
258 Ok(SecretKey::from(bytes))
259 }
260}
261
262impl Serialize for SecretKey {
263 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
264 where
265 S: serde::Serializer,
266 {
267 self.secret.serialize(serializer)
268 }
269}
270
271impl<'de> Deserialize<'de> for SecretKey {
272 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
273 where
274 D: serde::Deserializer<'de>,
275 {
276 let secret = SigningKey::deserialize(deserializer)?;
277 Ok(secret.into())
278 }
279}
280
281impl SecretKey {
282 pub fn public(&self) -> PublicKey {
284 self.secret.verifying_key().into()
285 }
286
287 pub fn generate<R: CryptoRngCore>(mut csprng: R) -> Self {
295 let secret = SigningKey::generate(&mut csprng);
296
297 Self { secret }
298 }
299
300 pub fn sign(&self, msg: &[u8]) -> Signature {
302 use ed25519_dalek::Signer;
303
304 self.secret.sign(msg)
305 }
306
307 pub fn to_bytes(&self) -> [u8; 32] {
310 self.secret.to_bytes()
311 }
312
313 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
315 let secret = SigningKey::from_bytes(bytes);
316 secret.into()
317 }
318
319 pub fn secret(&self) -> &SigningKey {
321 &self.secret
322 }
323}
324
325impl From<SigningKey> for SecretKey {
326 fn from(secret: SigningKey) -> Self {
327 SecretKey { secret }
328 }
329}
330
331impl From<[u8; 32]> for SecretKey {
332 fn from(value: [u8; 32]) -> Self {
333 Self::from_bytes(&value)
334 }
335}
336
337impl TryFrom<&[u8]> for SecretKey {
338 type Error = SignatureError;
339
340 #[inline]
341 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
342 let secret = SigningKey::try_from(bytes)?;
343 Ok(secret.into())
344 }
345}
346
347fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
348 let mut bytes = [0u8; 32];
349
350 let res = if s.len() == PublicKey::LENGTH * 2 {
351 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
353 } else {
354 let input = s.to_ascii_uppercase();
355 let input = input.as_bytes();
356 if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() {
357 return Err(DecodeInvalidLengthSnafu.build());
358 }
359 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
360 };
361 match res {
362 Ok(len) => {
363 if len != PublicKey::LENGTH {
364 return Err(DecodeInvalidLengthSnafu.build());
365 }
366 }
367 Err(partial) => return Err(partial.error.into()),
368 }
369 Ok(bytes)
370}
371
372#[cfg(test)]
373mod tests {
374 use data_encoding::HEXLOWER;
375
376 use super::*;
377
378 #[test]
379 fn test_public_key_postcard() {
380 let public_key =
381 PublicKey::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
382 .unwrap();
383 let bytes = postcard::to_stdvec(&public_key).unwrap();
384 let expected = HEXLOWER
385 .decode(b"ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
386 .unwrap();
387 assert_eq!(bytes, expected);
388 }
389
390 #[test]
391 fn public_key_postcard() {
392 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
393 let bytes = postcard::to_stdvec(&key).unwrap();
394 let key2: PublicKey = postcard::from_bytes(&bytes).unwrap();
395 assert_eq!(key, key2);
396 }
397
398 #[test]
399 fn public_key_json() {
400 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
401 let bytes = serde_json::to_string(&key).unwrap();
402 let key2: PublicKey = serde_json::from_str(&bytes).unwrap();
403 assert_eq!(key, key2);
404 }
405
406 #[test]
407 fn test_from_str() {
408 let key = SecretKey::generate(&mut rand::thread_rng());
409 assert_eq!(
410 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
411 .unwrap()
412 .to_bytes(),
413 key.to_bytes()
414 );
415
416 assert_eq!(
417 PublicKey::from_str(&key.public().to_string()).unwrap(),
418 key.public()
419 );
420 }
421
422 #[test]
423 fn test_regression_parse_node_id_panic() {
424 let not_a_node_id = "foobarbaz";
425 assert!(PublicKey::from_str(not_a_node_id).is_err());
426 }
427}