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) -> String {
138 data_encoding::HEXLOWER.encode(&self.as_bytes()[..5])
139 }
140
141 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
143}
144
145impl TryFrom<&[u8]> for PublicKey {
146 type Error = SignatureError;
147
148 #[inline]
149 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
150 let vk = VerifyingKey::try_from(bytes)?;
151 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
152 }
153}
154
155impl TryFrom<&[u8; 32]> for PublicKey {
156 type Error = SignatureError;
157
158 #[inline]
159 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
160 Self::from_bytes(bytes)
161 }
162}
163
164impl AsRef<[u8]> for PublicKey {
165 fn as_ref(&self) -> &[u8] {
166 self.as_bytes()
167 }
168}
169
170impl From<VerifyingKey> for PublicKey {
171 fn from(verifying_key: VerifyingKey) -> Self {
172 let key = verifying_key.to_bytes();
173 PublicKey(CompressedEdwardsY(key))
174 }
175}
176
177impl Debug for PublicKey {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 write!(
180 f,
181 "PublicKey({})",
182 data_encoding::HEXLOWER.encode(self.as_bytes())
183 )
184 }
185}
186
187impl Display for PublicKey {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 write!(f, "{}", data_encoding::HEXLOWER.encode(self.as_bytes()))
190 }
191}
192
193#[common_fields({
195 backtrace: Option<Backtrace>,
196 #[snafu(implicit)]
197 span_trace: n0_snafu::SpanTrace,
198})]
199#[derive(Snafu, Debug)]
200#[allow(missing_docs)]
201#[snafu(visibility(pub(crate)))]
202pub enum KeyParsingError {
203 #[snafu(transparent)]
205 Decode { source: data_encoding::DecodeError },
206 #[snafu(transparent)]
208 Key {
209 source: ed25519_dalek::SignatureError,
210 },
211 #[snafu(display("invalid length"))]
213 DecodeInvalidLength {},
214}
215
216impl FromStr for PublicKey {
220 type Err = KeyParsingError;
221
222 fn from_str(s: &str) -> Result<Self, Self::Err> {
223 let bytes = decode_base32_hex(s)?;
224
225 Ok(Self::from_bytes(&bytes)?)
226 }
227}
228
229#[derive(Clone)]
231pub struct SecretKey {
232 secret: SigningKey,
233}
234
235impl Debug for SecretKey {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 write!(f, "SecretKey(..)")
238 }
239}
240
241impl FromStr for SecretKey {
242 type Err = KeyParsingError;
243
244 fn from_str(s: &str) -> Result<Self, Self::Err> {
245 let bytes = decode_base32_hex(s)?;
246 Ok(SecretKey::from(bytes))
247 }
248}
249
250impl Serialize for SecretKey {
251 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
252 where
253 S: serde::Serializer,
254 {
255 self.secret.serialize(serializer)
256 }
257}
258
259impl<'de> Deserialize<'de> for SecretKey {
260 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
261 where
262 D: serde::Deserializer<'de>,
263 {
264 let secret = SigningKey::deserialize(deserializer)?;
265 Ok(secret.into())
266 }
267}
268
269impl SecretKey {
270 pub fn public(&self) -> PublicKey {
272 self.secret.verifying_key().into()
273 }
274
275 pub fn generate<R: CryptoRngCore>(mut csprng: R) -> Self {
283 let secret = SigningKey::generate(&mut csprng);
284
285 Self { secret }
286 }
287
288 pub fn sign(&self, msg: &[u8]) -> Signature {
290 use ed25519_dalek::Signer;
291
292 self.secret.sign(msg)
293 }
294
295 pub fn to_bytes(&self) -> [u8; 32] {
298 self.secret.to_bytes()
299 }
300
301 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
303 let secret = SigningKey::from_bytes(bytes);
304 secret.into()
305 }
306
307 pub fn secret(&self) -> &SigningKey {
309 &self.secret
310 }
311}
312
313impl From<SigningKey> for SecretKey {
314 fn from(secret: SigningKey) -> Self {
315 SecretKey { secret }
316 }
317}
318
319impl From<[u8; 32]> for SecretKey {
320 fn from(value: [u8; 32]) -> Self {
321 Self::from_bytes(&value)
322 }
323}
324
325impl TryFrom<&[u8]> for SecretKey {
326 type Error = SignatureError;
327
328 #[inline]
329 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
330 let secret = SigningKey::try_from(bytes)?;
331 Ok(secret.into())
332 }
333}
334
335fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> {
336 let mut bytes = [0u8; 32];
337
338 let res = if s.len() == PublicKey::LENGTH * 2 {
339 data_encoding::HEXLOWER.decode_mut(s.as_bytes(), &mut bytes)
341 } else {
342 let input = s.to_ascii_uppercase();
343 let input = input.as_bytes();
344 if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() {
345 return Err(DecodeInvalidLengthSnafu.build());
346 }
347 data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes)
348 };
349 match res {
350 Ok(len) => {
351 if len != PublicKey::LENGTH {
352 return Err(DecodeInvalidLengthSnafu.build());
353 }
354 }
355 Err(partial) => return Err(partial.error.into()),
356 }
357 Ok(bytes)
358}
359
360#[cfg(test)]
361mod tests {
362 use data_encoding::HEXLOWER;
363
364 use super::*;
365
366 #[test]
367 fn test_public_key_postcard() {
368 let public_key =
369 PublicKey::from_str("ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
370 .unwrap();
371 let bytes = postcard::to_stdvec(&public_key).unwrap();
372 let expected = HEXLOWER
373 .decode(b"ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6")
374 .unwrap();
375 assert_eq!(bytes, expected);
376 }
377
378 #[test]
379 fn public_key_postcard() {
380 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
381 let bytes = postcard::to_stdvec(&key).unwrap();
382 let key2: PublicKey = postcard::from_bytes(&bytes).unwrap();
383 assert_eq!(key, key2);
384 }
385
386 #[test]
387 fn public_key_json() {
388 let key = PublicKey::from_bytes(&[0; 32]).unwrap();
389 let bytes = serde_json::to_string(&key).unwrap();
390 let key2: PublicKey = serde_json::from_str(&bytes).unwrap();
391 assert_eq!(key, key2);
392 }
393
394 #[test]
395 fn test_from_str() {
396 let key = SecretKey::generate(&mut rand::thread_rng());
397 assert_eq!(
398 SecretKey::from_str(&HEXLOWER.encode(&key.to_bytes()))
399 .unwrap()
400 .to_bytes(),
401 key.to_bytes()
402 );
403
404 assert_eq!(
405 PublicKey::from_str(&key.public().to_string()).unwrap(),
406 key.public()
407 );
408 }
409
410 #[test]
411 fn test_regression_parse_node_id_panic() {
412 let not_a_node_id = "foobarbaz";
413 assert!(PublicKey::from_str(not_a_node_id).is_err());
414 }
415}