1use std::{
4 borrow::Borrow,
5 cmp::{Ord, PartialOrd},
6 fmt::{Debug, Display},
7 hash::Hash,
8 str::FromStr,
9};
10
11use curve25519_dalek::edwards::CompressedEdwardsY;
12pub use ed25519_dalek::{Signature, SignatureError};
13use ed25519_dalek::{SigningKey, VerifyingKey};
14use nested_enum_utils::common_fields;
15use rand_core::CryptoRngCore;
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 PartialOrd for PublicKey {
34 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
35 Some(self.cmp(other))
36 }
37}
38
39impl Ord for PublicKey {
40 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
41 self.0.as_bytes().cmp(other.0.as_bytes())
42 }
43}
44
45pub type NodeId = PublicKey;
58
59impl Hash for PublicKey {
60 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
61 self.0.hash(state);
62 }
63}
64
65impl Serialize for PublicKey {
66 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67 where
68 S: serde::Serializer,
69 {
70 if serializer.is_human_readable() {
71 serializer.serialize_str(&self.to_string())
72 } else {
73 self.0.as_bytes().serialize(serializer)
74 }
75 }
76}
77
78impl<'de> Deserialize<'de> for PublicKey {
79 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80 where
81 D: serde::Deserializer<'de>,
82 {
83 if deserializer.is_human_readable() {
84 let s = String::deserialize(deserializer)?;
85 Self::from_str(&s).map_err(serde::de::Error::custom)
86 } else {
87 let data: [u8; 32] = serde::Deserialize::deserialize(deserializer)?;
88 Self::try_from(data.as_ref()).map_err(serde::de::Error::custom)
89 }
90 }
91}
92
93impl PublicKey {
94 pub fn as_bytes(&self) -> &[u8; 32] {
96 self.0.as_bytes()
97 }
98
99 pub fn public(&self) -> VerifyingKey {
101 VerifyingKey::from_bytes(self.0.as_bytes()).expect("already verified")
102 }
103
104 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
112 let key = VerifyingKey::from_bytes(bytes)?;
113 let y = CompressedEdwardsY(key.to_bytes());
114 Ok(Self(y))
115 }
116
117 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
123 self.public().verify_strict(message, signature)
124 }
125
126 pub fn fmt_short(&self) -> String {
129 data_encoding::HEXLOWER.encode(&self.as_bytes()[..5])
130 }
131
132 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
134}
135
136impl TryFrom<&[u8]> for PublicKey {
137 type Error = SignatureError;
138
139 #[inline]
140 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
141 let vk = VerifyingKey::try_from(bytes)?;
142 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
143 }
144}
145
146impl TryFrom<&[u8; 32]> for PublicKey {
147 type Error = SignatureError;
148
149 #[inline]
150 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
151 Self::from_bytes(bytes)
152 }
153}
154
155impl AsRef<[u8]> for PublicKey {
156 fn as_ref(&self) -> &[u8] {
157 self.as_bytes()
158 }
159}
160
161impl From<VerifyingKey> for PublicKey {
162 fn from(verifying_key: VerifyingKey) -> Self {
163 let key = verifying_key.to_bytes();
164 PublicKey(CompressedEdwardsY(key))
165 }
166}
167
168impl Debug for PublicKey {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 write!(
171 f,
172 "PublicKey({})",
173 data_encoding::HEXLOWER.encode(self.as_bytes())
174 )
175 }
176}
177
178impl Display for PublicKey {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 write!(f, "{}", data_encoding::HEXLOWER.encode(self.as_bytes()))
181 }
182}
183
184#[common_fields({
186 backtrace: Option<Backtrace>,
187 #[snafu(implicit)]
188 span_trace: n0_snafu::SpanTrace,
189})]
190#[derive(Snafu, Debug)]
191#[allow(missing_docs)]
192#[snafu(visibility(pub(crate)))]
193pub enum KeyParsingError {
194 #[snafu(transparent)]
196 Decode { source: data_encoding::DecodeError },
197 #[snafu(transparent)]
199 Key {
200 source: ed25519_dalek::SignatureError,
201 },
202 #[snafu(display("invalid length"))]
204 DecodeInvalidLength {},
205}
206
207impl FromStr for PublicKey {
211 type Err = KeyParsingError;
212
213 fn from_str(s: &str) -> Result<Self, Self::Err> {
214 let bytes = decode_base32_hex(s)?;
215
216 Ok(Self::from_bytes(&bytes)?)
217 }
218}
219
220#[derive(Clone)]
222pub struct SecretKey {
223 secret: SigningKey,
224}
225
226impl Debug for SecretKey {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 write!(f, "SecretKey(..)")
229 }
230}
231
232impl FromStr for SecretKey {
233 type Err = KeyParsingError;
234
235 fn from_str(s: &str) -> Result<Self, Self::Err> {
236 let bytes = decode_base32_hex(s)?;
237 Ok(SecretKey::from(bytes))
238 }
239}
240
241impl Serialize for SecretKey {
242 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243 where
244 S: serde::Serializer,
245 {
246 self.secret.serialize(serializer)
247 }
248}
249
250impl<'de> Deserialize<'de> for SecretKey {
251 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
252 where
253 D: serde::Deserializer<'de>,
254 {
255 let secret = SigningKey::deserialize(deserializer)?;
256 Ok(secret.into())
257 }
258}
259
260impl SecretKey {
261 pub fn public(&self) -> PublicKey {
263 self.secret.verifying_key().into()
264 }
265
266 pub fn generate<R: CryptoRngCore>(mut csprng: R) -> Self {
274 let secret = SigningKey::generate(&mut csprng);
275
276 Self { secret }
277 }
278
279 pub fn sign(&self, msg: &[u8]) -> Signature {
281 use ed25519_dalek::Signer;
282
283 self.secret.sign(msg)
284 }
285
286 pub fn to_bytes(&self) -> [u8; 32] {
289 self.secret.to_bytes()
290 }
291
292 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
294 let secret = SigningKey::from_bytes(bytes);
295 secret.into()
296 }
297
298 pub fn secret(&self) -> &SigningKey {
300 &self.secret
301 }
302}
303
304impl From<SigningKey> for SecretKey {
305 fn from(secret: SigningKey) -> Self {
306 SecretKey { secret }
307 }
308}
309
310impl From<[u8; 32]> for SecretKey {
311 fn from(value: [u8; 32]) -> Self {
312 Self::from_bytes(&value)
313 }
314}
315
316impl TryFrom<&[u8]> for SecretKey {
317 type Error = SignatureError;
318
319 #[inline]
320 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
321 let secret = SigningKey::try_from(bytes)?;
322 Ok(secret.into())
323 }
324}
325
326fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
327 let mut bytes = [0u8; 32];
328
329 let res = if s.len() == PublicKey::LENGTH * 2 {
330 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
332 } else {
333 let input = s.to_ascii_uppercase();
334 let input = input.as_bytes();
335 if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() {
336 return Err(DecodeInvalidLengthSnafu.build());
337 }
338 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
339 };
340 match res {
341 Ok(len) => {
342 if len != PublicKey::LENGTH {
343 return Err(DecodeInvalidLengthSnafu.build());
344 }
345 }
346 Err(partial) => return Err(partial.error.into()),
347 }
348 Ok(bytes)
349}
350
351#[cfg(test)]
352mod tests {
353 use data_encoding::HEXLOWER;
354
355 use super::*;
356
357 #[test]
358 fn test_public_key_postcard() {
359 let public_key =
360 PublicKey::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
361 .unwrap();
362 let bytes = postcard::to_stdvec(&public_key).unwrap();
363 let expected = HEXLOWER
364 .decode(b"ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
365 .unwrap();
366 assert_eq!(bytes, expected);
367 }
368
369 #[test]
370 fn public_key_postcard() {
371 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
372 let bytes = postcard::to_stdvec(&key).unwrap();
373 let key2: PublicKey = postcard::from_bytes(&bytes).unwrap();
374 assert_eq!(key, key2);
375 }
376
377 #[test]
378 fn public_key_json() {
379 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
380 let bytes = serde_json::to_string(&key).unwrap();
381 let key2: PublicKey = serde_json::from_str(&bytes).unwrap();
382 assert_eq!(key, key2);
383 }
384
385 #[test]
386 fn test_from_str() {
387 let key = SecretKey::generate(&mut rand::thread_rng());
388 assert_eq!(
389 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
390 .unwrap()
391 .to_bytes(),
392 key.to_bytes()
393 );
394
395 assert_eq!(
396 PublicKey::from_str(&key.public().to_string()).unwrap(),
397 key.public()
398 );
399 }
400
401 #[test]
402 fn test_regression_parse_node_id_panic() {
403 let not_a_node_id = "foobarbaz";
404 assert!(PublicKey::from_str(not_a_node_id).is_err());
405 }
406}