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;
13use ed25519_dalek::{SignatureError, SigningKey, VerifyingKey};
14use rand_core::CryptoRngCore;
15use serde::{Deserialize, Serialize};
16
17#[derive(Clone, Copy, PartialEq, Eq)]
22#[repr(transparent)]
23pub struct PublicKey(CompressedEdwardsY);
24
25impl Borrow<[u8; 32]> for PublicKey {
26 fn borrow(&self) -> &[u8; 32] {
27 self.as_bytes()
28 }
29}
30
31impl PartialOrd for PublicKey {
32 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
33 Some(self.cmp(other))
34 }
35}
36
37impl Ord for PublicKey {
38 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
39 self.0.as_bytes().cmp(other.0.as_bytes())
40 }
41}
42
43pub type NodeId = PublicKey;
56
57impl Hash for PublicKey {
58 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
59 self.0.hash(state);
60 }
61}
62
63impl Serialize for PublicKey {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: serde::Serializer,
67 {
68 if serializer.is_human_readable() {
69 serializer.serialize_str(&self.to_string())
70 } else {
71 self.0.as_bytes().serialize(serializer)
72 }
73 }
74}
75
76impl<'de> Deserialize<'de> for PublicKey {
77 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78 where
79 D: serde::Deserializer<'de>,
80 {
81 if deserializer.is_human_readable() {
82 let s = String::deserialize(deserializer)?;
83 Self::from_str(&s).map_err(serde::de::Error::custom)
84 } else {
85 let data: [u8; 32] = serde::Deserialize::deserialize(deserializer)?;
86 Self::try_from(data.as_ref()).map_err(serde::de::Error::custom)
87 }
88 }
89}
90
91impl PublicKey {
92 pub fn as_bytes(&self) -> &[u8; 32] {
94 self.0.as_bytes()
95 }
96
97 pub fn public(&self) -> VerifyingKey {
99 VerifyingKey::from_bytes(self.0.as_bytes()).expect("already verified")
100 }
101
102 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
110 let key = VerifyingKey::from_bytes(bytes)?;
111 let y = CompressedEdwardsY(key.to_bytes());
112 Ok(Self(y))
113 }
114
115 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
121 self.public().verify_strict(message, signature)
122 }
123
124 pub fn fmt_short(&self) -> String {
127 data_encoding::HEXLOWER.encode(&self.as_bytes()[..5])
128 }
129
130 pub const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
132}
133
134impl TryFrom<&[u8]> for PublicKey {
135 type Error = SignatureError;
136
137 #[inline]
138 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
139 let vk = VerifyingKey::try_from(bytes)?;
140 Ok(Self(CompressedEdwardsY(vk.to_bytes())))
141 }
142}
143
144impl TryFrom<&[u8; 32]> for PublicKey {
145 type Error = SignatureError;
146
147 #[inline]
148 fn try_from(bytes: &[u8; 32]) -> Result<Self, Self::Error> {
149 Self::from_bytes(bytes)
150 }
151}
152
153impl AsRef<[u8]> for PublicKey {
154 fn as_ref(&self) -> &[u8] {
155 self.as_bytes()
156 }
157}
158
159impl From<VerifyingKey> for PublicKey {
160 fn from(verifying_key: VerifyingKey) -> Self {
161 let key = verifying_key.to_bytes();
162 PublicKey(CompressedEdwardsY(key))
163 }
164}
165
166impl Debug for PublicKey {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 write!(
169 f,
170 "PublicKey({})",
171 data_encoding::HEXLOWER.encode(self.as_bytes())
172 )
173 }
174}
175
176impl Display for PublicKey {
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178 write!(f, "{}", data_encoding::HEXLOWER.encode(self.as_bytes()))
179 }
180}
181
182#[derive(thiserror::Error, Debug)]
184pub enum KeyParsingError {
185 #[error("decoding: {0}")]
187 Decode(#[from] data_encoding::DecodeError),
188 #[error("key: {0}")]
190 Key(#[from] ed25519_dalek::SignatureError),
191 #[error("invalid length")]
193 DecodeInvalidLength,
194}
195
196impl FromStr for PublicKey {
200 type Err = KeyParsingError;
201
202 fn from_str(s: &str) -> Result<Self, Self::Err> {
203 let bytes = decode_base32_hex(s)?;
204
205 Ok(Self::from_bytes(&bytes)?)
206 }
207}
208
209#[derive(Clone)]
211pub struct SecretKey {
212 secret: SigningKey,
213}
214
215impl Debug for SecretKey {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 write!(f, "SecretKey(..)")
218 }
219}
220
221impl Display for SecretKey {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 write!(
225 f,
226 "{}",
227 data_encoding::HEXLOWER.encode(self.secret.as_bytes())
228 )
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(KeyParsingError::DecodeInvalidLength);
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(KeyParsingError::DecodeInvalidLength);
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_display_from_str() {
387 let key = SecretKey::generate(&mut rand::thread_rng());
388 assert_eq!(
389 SecretKey::from_str(&key.to_string()).unwrap().to_bytes(),
390 key.to_bytes()
391 );
392
393 assert_eq!(
394 PublicKey::from_str(&key.public().to_string()).unwrap(),
395 key.public()
396 );
397 }
398
399 #[test]
400 fn test_regression_parse_node_id_panic() {
401 let not_a_node_id = "foobarbaz";
402 assert!(PublicKey::from_str(not_a_node_id).is_err());
403 }
404}