1use ed25519_dalek::{
4 SecretKey, Signature, SignatureError, Signer, SigningKey, Verifier, VerifyingKey,
5};
6use std::{
7 fmt::{self, Debug, Display, Formatter},
8 hash::Hash,
9 str::FromStr,
10};
11
12use serde::{Deserialize, Serialize};
13
14#[derive(Clone, PartialEq, Eq)]
15pub struct Keypair(pub(crate) SigningKey);
17
18impl Keypair {
19 pub fn random() -> Keypair {
21 let mut bytes = [0u8; 32];
22
23 getrandom::getrandom(&mut bytes).expect("getrandom failed");
24
25 let signing_key: SigningKey = SigningKey::from_bytes(&bytes);
26
27 Keypair(signing_key)
28 }
29
30 pub fn from_secret_key(secret_key: &SecretKey) -> Keypair {
32 Keypair(SigningKey::from_bytes(secret_key))
33 }
34
35 pub fn sign(&self, message: &[u8]) -> Signature {
37 self.0.sign(message)
38 }
39
40 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
42 self.0.verify(message, signature)
43 }
44
45 pub fn secret_key(&self) -> SecretKey {
47 self.0.to_bytes()
48 }
49
50 pub fn public_key(&self) -> PublicKey {
52 PublicKey(self.0.verifying_key())
53 }
54
55 pub fn to_z32(&self) -> String {
57 self.public_key().to_string()
58 }
59
60 pub fn to_uri_string(&self) -> String {
62 self.public_key().to_uri_string()
63 }
64}
65
66#[derive(Clone, Eq, PartialEq, Hash)]
70pub struct PublicKey(pub(crate) VerifyingKey);
71
72impl PublicKey {
73 pub fn to_z32(&self) -> String {
75 self.to_string()
76 }
77
78 pub fn to_uri_string(&self) -> String {
80 format!("pk:{self}")
81 }
82
83 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
85 self.0.verify(message, signature)
86 }
87
88 pub fn verifying_key(&self) -> &VerifyingKey {
90 &self.0
91 }
92
93 pub fn to_bytes(&self) -> [u8; 32] {
95 self.0.to_bytes()
96 }
97
98 pub fn as_bytes(&self) -> &[u8; 32] {
100 self.0.as_bytes()
101 }
102}
103
104impl AsRef<Keypair> for Keypair {
105 fn as_ref(&self) -> &Keypair {
106 self
107 }
108}
109
110impl AsRef<PublicKey> for PublicKey {
111 fn as_ref(&self) -> &PublicKey {
112 self
113 }
114}
115
116impl TryFrom<&[u8]> for PublicKey {
117 type Error = PublicKeyError;
118
119 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
120 let bytes_32: &[u8; 32] = bytes
121 .try_into()
122 .map_err(|_| PublicKeyError::InvalidPublicKeyLength(bytes.len()))?;
123
124 Ok(Self(
125 VerifyingKey::from_bytes(bytes_32)
126 .map_err(|_| PublicKeyError::InvalidEd25519PublicKey)?,
127 ))
128 }
129}
130
131impl TryFrom<&[u8; 32]> for PublicKey {
132 type Error = PublicKeyError;
133
134 fn try_from(public: &[u8; 32]) -> Result<Self, Self::Error> {
135 Ok(Self(
136 VerifyingKey::from_bytes(public)
137 .map_err(|_| PublicKeyError::InvalidEd25519PublicKey)?,
138 ))
139 }
140}
141
142impl From<VerifyingKey> for PublicKey {
143 fn from(verifying_key: VerifyingKey) -> Self {
144 Self(verifying_key)
145 }
146}
147
148impl FromStr for PublicKey {
149 type Err = PublicKeyError;
150
151 fn from_str(s: &str) -> Result<Self, Self::Err> {
166 let mut s = s;
167
168 if s.len() > 52 {
169 s = s.split_once(':').map(|tuple| tuple.1).unwrap_or(s);
171
172 if s.len() > 52 {
173 s = s.strip_prefix("//").unwrap_or(s);
175
176 if s.len() > 52 {
177 s = s.split_once('@').map(|tuple| tuple.1).unwrap_or(s);
179
180 if s.len() > 52 {
181 s = s.split_once(':').map(|tuple| tuple.0).unwrap_or(s);
183
184 if s.len() > 52 {
185 s = s.split_once('/').map(|tuple| tuple.0).unwrap_or(s);
187
188 if s.len() > 52 {
189 s = s.split_once('?').map(|tuple| tuple.0).unwrap_or(s);
191
192 if s.len() > 52 {
193 s = s.split_once('#').map(|tuple| tuple.0).unwrap_or(s);
195
196 if s.len() > 52 {
197 if s.ends_with('.') {
198 s = s.trim_matches('.');
200 }
201
202 s = s.rsplit_once('.').map(|tuple| tuple.1).unwrap_or(s);
203 }
204 }
205 }
206 }
207 }
208 }
209 }
210 }
211
212 let bytes = if let Some(v) = base32::decode(base32::Alphabet::Z, s) {
213 Ok(v)
214 } else {
215 Err(PublicKeyError::InvalidPublicKeyEncoding)
216 }?;
217
218 bytes.as_slice().try_into()
219 }
220}
221
222impl TryFrom<&str> for PublicKey {
223 type Error = PublicKeyError;
224
225 fn try_from(s: &str) -> Result<PublicKey, PublicKeyError> {
226 PublicKey::from_str(s)
227 }
228}
229
230impl TryFrom<String> for PublicKey {
231 type Error = PublicKeyError;
232
233 fn try_from(s: String) -> Result<PublicKey, PublicKeyError> {
234 s.as_str().try_into()
235 }
236}
237
238impl TryFrom<&String> for PublicKey {
239 type Error = PublicKeyError;
240
241 fn try_from(s: &String) -> Result<PublicKey, PublicKeyError> {
242 s.try_into()
243 }
244}
245
246impl Display for PublicKey {
247 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
248 write!(
249 f,
250 "{}",
251 base32::encode(base32::Alphabet::Z, self.0.as_bytes())
252 )
253 }
254}
255
256impl Display for Keypair {
257 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
258 write!(f, "{}", self.public_key())
259 }
260}
261
262impl Debug for Keypair {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 write!(f, "Keypair({})", self.public_key())
265 }
266}
267
268impl Debug for PublicKey {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 write!(f, "PublicKey({self})")
271 }
272}
273
274impl Serialize for PublicKey {
275 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
276 where
277 S: serde::Serializer,
278 {
279 let bytes = self.to_bytes();
280 bytes.serialize(serializer)
281 }
282}
283
284impl<'de> Deserialize<'de> for PublicKey {
285 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
286 where
287 D: serde::Deserializer<'de>,
288 {
289 let bytes: [u8; 32] = Deserialize::deserialize(deserializer)?;
290
291 (&bytes).try_into().map_err(serde::de::Error::custom)
292 }
293}
294
295#[derive(thiserror::Error, Debug, PartialEq, Eq)]
296pub enum PublicKeyError {
298 #[error("Invalid PublicKey length, expected 32 bytes but got: {0}")]
299 InvalidPublicKeyLength(usize),
301
302 #[error("Invalid Ed25519 publickey; Cannot decompress Edwards point")]
303 InvalidEd25519PublicKey,
305
306 #[error("Invalid PublicKey encoding")]
307 InvalidPublicKeyEncoding,
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314
315 #[test]
316 fn pkarr_key_generate() {
317 let key1 = Keypair::random();
318 let key2 = Keypair::from_secret_key(&key1.secret_key());
319
320 assert_eq!(key1.public_key(), key2.public_key())
321 }
322
323 #[test]
324 fn zbase32() {
325 let key1 = Keypair::random();
326 let _z32 = key1.public_key().to_string();
327
328 let key2 = Keypair::from_secret_key(&key1.secret_key());
329
330 assert_eq!(key1.public_key(), key2.public_key())
331 }
332
333 #[test]
334 fn sign_verify() {
335 let keypair = Keypair::random();
336
337 let message = b"Hello, world!";
338 let signature = keypair.sign(message);
339
340 assert!(keypair.verify(message, &signature).is_ok());
341
342 let public_key = keypair.public_key();
343 assert!(public_key.verify(message, &signature).is_ok());
344 }
345
346 #[test]
347 fn from_string() {
348 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
349 let expected = [
350 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
351 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
352 ];
353
354 let public_key: PublicKey = str.try_into().unwrap();
355 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
356 }
357
358 #[test]
359 fn to_uri() {
360 let bytes = [
361 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
362 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
363 ];
364 let expected = "pk:yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
365
366 let public_key: PublicKey = (&bytes).try_into().unwrap();
367
368 assert_eq!(public_key.to_uri_string(), expected);
369 }
370
371 #[test]
372 fn from_uri() {
373 let str = "pk:yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
374 let expected = [
375 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
376 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
377 ];
378
379 let public_key: PublicKey = str.try_into().unwrap();
380 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
381 }
382
383 #[test]
384 fn from_uri_with_path() {
385 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no///foo/bar";
386 let expected = [
387 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
388 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
389 ];
390
391 let public_key: PublicKey = str.try_into().unwrap();
392 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
393 }
394
395 #[test]
396 fn from_uri_with_query() {
397 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no?foo=bar";
398 let expected = [
399 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
400 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
401 ];
402
403 let public_key: PublicKey = str.try_into().unwrap();
404 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
405 }
406
407 #[test]
408 fn from_uri_with_hash() {
409 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
410 let expected = [
411 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
412 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
413 ];
414
415 let public_key: PublicKey = str.try_into().unwrap();
416 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
417 }
418
419 #[test]
420 fn from_uri_with_subdomain() {
421 let str = "https://foo.bar.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
422 let expected = [
423 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
424 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
425 ];
426
427 let public_key: PublicKey = str.try_into().unwrap();
428 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
429 }
430
431 #[test]
432 fn from_uri_with_trailing_dot() {
433 let str = "https://foo.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no.";
434 let expected = [
435 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
436 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
437 ];
438
439 let public_key: PublicKey = str.try_into().unwrap();
440 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
441 }
442
443 #[test]
444 fn from_uri_with_username() {
445 let str = "https://foo@yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
446 let expected = [
447 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
448 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
449 ];
450
451 let public_key: PublicKey = str.try_into().unwrap();
452 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
453 }
454
455 #[test]
456 fn from_uri_with_port() {
457 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no:8888";
458 let expected = [
459 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
460 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
461 ];
462
463 let public_key: PublicKey = str.try_into().unwrap();
464 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
465 }
466
467 #[test]
468 fn from_uri_complex() {
469 let str =
470 "https://foo@bar.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no.:8888?q=v&a=b#foo";
471 let expected = [
472 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
473 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
474 ];
475
476 let public_key: PublicKey = str.try_into().unwrap();
477 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
478 }
479
480 #[test]
481 fn serde() {
482 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
483 let expected = [
484 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
485 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
486 ];
487
488 let public_key: PublicKey = str.try_into().unwrap();
489
490 let bytes = postcard::to_allocvec(&public_key).unwrap();
491
492 assert_eq!(bytes, expected)
493 }
494
495 #[test]
496 fn from_uri_multiple_pkarr() {
497 let str =
500 "https://o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
501 let expected = [
502 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
503 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
504 ];
505
506 let public_key: PublicKey = str.try_into().unwrap();
507 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
508 }
509
510 #[cfg(all(not(target_family = "wasm"), feature = "tls"))]
511 #[test]
512 fn pkcs8() {
513 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
514 let public_key: PublicKey = str.try_into().unwrap();
515
516 let der = public_key.to_public_key_der();
517
518 assert_eq!(
519 der.as_bytes(),
520 [
521 48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254,
525 14, 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
526 ]
527 )
528 }
529
530 #[cfg(all(not(target_family = "wasm"), feature = "tls"))]
531 #[test]
532 fn certificate() {
533 use rustls::SignatureAlgorithm;
534
535 let keypair = Keypair::from_secret_key(&[0; 32]);
536
537 let certified_key = keypair.to_rpk_certified_key();
538
539 assert_eq!(certified_key.key.algorithm(), SignatureAlgorithm::ED25519);
540
541 assert_eq!(
542 certified_key.end_entity_cert().unwrap().as_ref(),
543 [
544 48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 59, 106, 39, 188, 206, 182, 164, 45,
545 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, 21, 119, 29, 226, 67, 166, 58, 192,
546 72, 161, 139, 89, 218, 41,
547 ]
548 )
549 }
550
551 #[test]
552 fn invalid_key() {
553 let key = "c1bkg8tfsyy8wcedtmw4fwhdmm7bbzhgg3z58tf43m5ow8w9mbus";
554
555 assert_eq!(
556 PublicKey::try_from(key),
557 Err(PublicKeyError::InvalidEd25519PublicKey)
558 );
559 }
560}