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::CryptoRng;
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: CryptoRng + ?Sized>(csprng: &mut R) -> Self {
294 let secret = SigningKey::generate(csprng);
295
296 Self { secret }
297 }
298
299 pub fn sign(&self, msg: &[u8]) -> Signature {
301 use ed25519_dalek::Signer;
302
303 self.secret.sign(msg)
304 }
305
306 pub fn to_bytes(&self) -> [u8; 32] {
309 self.secret.to_bytes()
310 }
311
312 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
314 let secret = SigningKey::from_bytes(bytes);
315 secret.into()
316 }
317
318 pub fn secret(&self) -> &SigningKey {
320 &self.secret
321 }
322}
323
324impl From<SigningKey> for SecretKey {
325 fn from(secret: SigningKey) -> Self {
326 SecretKey { secret }
327 }
328}
329
330impl From<[u8; 32]> for SecretKey {
331 fn from(value: [u8; 32]) -> Self {
332 Self::from_bytes(&value)
333 }
334}
335
336impl TryFrom<&[u8]> for SecretKey {
337 type Error = SignatureError;
338
339 #[inline]
340 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
341 let secret = SigningKey::try_from(bytes)?;
342 Ok(secret.into())
343 }
344}
345
346fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
347 let mut bytes = [0u8; 32];
348
349 let res = if s.len() == PublicKey::LENGTH * 2 {
350 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
352 } else {
353 let input = s.to_ascii_uppercase();
354 let input = input.as_bytes();
355 if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() {
356 return Err(DecodeInvalidLengthSnafu.build());
357 }
358 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
359 };
360 match res {
361 Ok(len) => {
362 if len != PublicKey::LENGTH {
363 return Err(DecodeInvalidLengthSnafu.build());
364 }
365 }
366 Err(partial) => return Err(partial.error.into()),
367 }
368 Ok(bytes)
369}
370
371#[cfg(test)]
372mod tests {
373 use data_encoding::HEXLOWER;
374 use rand::SeedableRng;
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 mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64);
409 let key = SecretKey::generate(&mut rng);
410 assert_eq!(
411 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
412 .unwrap()
413 .to_bytes(),
414 key.to_bytes()
415 );
416
417 assert_eq!(
418 PublicKey::from_str(&key.public().to_string()).unwrap(),
419 key.public()
420 );
421 }
422
423 #[test]
424 fn test_regression_parse_node_id_panic() {
425 let not_a_node_id = "foobarbaz";
426 assert!(PublicKey::from_str(not_a_node_id).is_err());
427 }
428}