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 FromStr for PublicKey {
143 type Err = PublicKeyError;
144
145 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 let mut s = s;
161
162 if s.len() > 52 {
163 s = s.split_once(':').map(|tuple| tuple.1).unwrap_or(s);
165
166 if s.len() > 52 {
167 s = s.strip_prefix("//").unwrap_or(s);
169
170 if s.len() > 52 {
171 s = s.split_once('@').map(|tuple| tuple.1).unwrap_or(s);
173
174 if s.len() > 52 {
175 s = s.split_once(':').map(|tuple| tuple.0).unwrap_or(s);
177
178 if s.len() > 52 {
179 s = s.split_once('/').map(|tuple| tuple.0).unwrap_or(s);
181
182 if s.len() > 52 {
183 s = s.split_once('?').map(|tuple| tuple.0).unwrap_or(s);
185
186 if s.len() > 52 {
187 s = s.split_once('#').map(|tuple| tuple.0).unwrap_or(s);
189
190 if s.len() > 52 {
191 if s.ends_with('.') {
192 s = s.trim_matches('.');
194 }
195
196 s = s.rsplit_once('.').map(|tuple| tuple.1).unwrap_or(s);
197 }
198 }
199 }
200 }
201 }
202 }
203 }
204 }
205
206 let bytes = if let Some(v) = base32::decode(base32::Alphabet::Z, s) {
207 Ok(v)
208 } else {
209 Err(PublicKeyError::InvalidPublicKeyEncoding)
210 }?;
211
212 bytes.as_slice().try_into()
213 }
214}
215
216impl TryFrom<&str> for PublicKey {
217 type Error = PublicKeyError;
218
219 fn try_from(s: &str) -> Result<PublicKey, PublicKeyError> {
220 PublicKey::from_str(s)
221 }
222}
223
224impl TryFrom<String> for PublicKey {
225 type Error = PublicKeyError;
226
227 fn try_from(s: String) -> Result<PublicKey, PublicKeyError> {
228 s.as_str().try_into()
229 }
230}
231
232impl TryFrom<&String> for PublicKey {
233 type Error = PublicKeyError;
234
235 fn try_from(s: &String) -> Result<PublicKey, PublicKeyError> {
236 s.try_into()
237 }
238}
239
240impl Display for PublicKey {
241 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
242 write!(
243 f,
244 "{}",
245 base32::encode(base32::Alphabet::Z, self.0.as_bytes())
246 )
247 }
248}
249
250impl Display for Keypair {
251 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
252 write!(f, "{}", self.public_key())
253 }
254}
255
256impl Debug for Keypair {
257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258 write!(f, "Keypair({})", self.public_key())
259 }
260}
261
262impl Debug for PublicKey {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 write!(f, "PublicKey({})", self)
265 }
266}
267
268impl Serialize for PublicKey {
269 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
270 where
271 S: serde::Serializer,
272 {
273 let bytes = self.to_bytes();
274 bytes.serialize(serializer)
275 }
276}
277
278impl<'de> Deserialize<'de> for PublicKey {
279 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
280 where
281 D: serde::Deserializer<'de>,
282 {
283 let bytes: [u8; 32] = Deserialize::deserialize(deserializer)?;
284
285 (&bytes).try_into().map_err(serde::de::Error::custom)
286 }
287}
288
289#[derive(thiserror::Error, Debug, PartialEq, Eq)]
290pub enum PublicKeyError {
292 #[error("Invalid PublicKey length, expected 32 bytes but got: {0}")]
293 InvalidPublicKeyLength(usize),
295
296 #[error("Invalid Ed25519 publickey; Cannot decompress Edwards point")]
297 InvalidEd25519PublicKey,
299
300 #[error("Invalid PublicKey encoding")]
301 InvalidPublicKeyEncoding,
303}
304
305#[cfg(test)]
306mod tests {
307 use super::*;
308
309 #[test]
310 fn pkarr_key_generate() {
311 let key1 = Keypair::random();
312 let key2 = Keypair::from_secret_key(&key1.secret_key());
313
314 assert_eq!(key1.public_key(), key2.public_key())
315 }
316
317 #[test]
318 fn zbase32() {
319 let key1 = Keypair::random();
320 let _z32 = key1.public_key().to_string();
321
322 let key2 = Keypair::from_secret_key(&key1.secret_key());
323
324 assert_eq!(key1.public_key(), key2.public_key())
325 }
326
327 #[test]
328 fn sign_verify() {
329 let keypair = Keypair::random();
330
331 let message = b"Hello, world!";
332 let signature = keypair.sign(message);
333
334 assert!(keypair.verify(message, &signature).is_ok());
335
336 let public_key = keypair.public_key();
337 assert!(public_key.verify(message, &signature).is_ok());
338 }
339
340 #[test]
341 fn from_string() {
342 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
343 let expected = [
344 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
345 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
346 ];
347
348 let public_key: PublicKey = str.try_into().unwrap();
349 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
350 }
351
352 #[test]
353 fn to_uri() {
354 let bytes = [
355 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
356 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
357 ];
358 let expected = "pk:yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
359
360 let public_key: PublicKey = (&bytes).try_into().unwrap();
361
362 assert_eq!(public_key.to_uri_string(), expected);
363 }
364
365 #[test]
366 fn from_uri() {
367 let str = "pk:yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
368 let expected = [
369 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
370 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
371 ];
372
373 let public_key: PublicKey = str.try_into().unwrap();
374 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
375 }
376
377 #[test]
378 fn from_uri_with_path() {
379 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no///foo/bar";
380 let expected = [
381 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
382 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
383 ];
384
385 let public_key: PublicKey = str.try_into().unwrap();
386 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
387 }
388
389 #[test]
390 fn from_uri_with_query() {
391 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no?foo=bar";
392 let expected = [
393 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
394 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
395 ];
396
397 let public_key: PublicKey = str.try_into().unwrap();
398 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
399 }
400
401 #[test]
402 fn from_uri_with_hash() {
403 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
404 let expected = [
405 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
406 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
407 ];
408
409 let public_key: PublicKey = str.try_into().unwrap();
410 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
411 }
412
413 #[test]
414 fn from_uri_with_subdomain() {
415 let str = "https://foo.bar.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
416 let expected = [
417 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
418 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
419 ];
420
421 let public_key: PublicKey = str.try_into().unwrap();
422 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
423 }
424
425 #[test]
426 fn from_uri_with_trailing_dot() {
427 let str = "https://foo.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no.";
428 let expected = [
429 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
430 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
431 ];
432
433 let public_key: PublicKey = str.try_into().unwrap();
434 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
435 }
436
437 #[test]
438 fn from_uri_with_username() {
439 let str = "https://foo@yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no#foo";
440 let expected = [
441 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
442 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
443 ];
444
445 let public_key: PublicKey = str.try_into().unwrap();
446 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
447 }
448
449 #[test]
450 fn from_uri_with_port() {
451 let str = "https://yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no:8888";
452 let expected = [
453 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
454 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
455 ];
456
457 let public_key: PublicKey = str.try_into().unwrap();
458 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
459 }
460
461 #[test]
462 fn from_uri_complex() {
463 let str =
464 "https://foo@bar.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no.:8888?q=v&a=b#foo";
465 let expected = [
466 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
467 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
468 ];
469
470 let public_key: PublicKey = str.try_into().unwrap();
471 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
472 }
473
474 #[test]
475 fn serde() {
476 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
477 let expected = [
478 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
479 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
480 ];
481
482 let public_key: PublicKey = str.try_into().unwrap();
483
484 let bytes = postcard::to_allocvec(&public_key).unwrap();
485
486 assert_eq!(bytes, expected)
487 }
488
489 #[test]
490 fn from_uri_multiple_pkarr() {
491 let str =
494 "https://o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy.yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
495 let expected = [
496 1, 180, 103, 163, 183, 145, 58, 178, 122, 4, 168, 237, 242, 243, 251, 7, 76, 254, 14,
497 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
498 ];
499
500 let public_key: PublicKey = str.try_into().unwrap();
501 assert_eq!(public_key.verifying_key().as_bytes(), &expected);
502 }
503
504 #[cfg(all(not(target_family = "wasm"), feature = "tls"))]
505 #[test]
506 fn pkcs8() {
507 let str = "yg4gxe7z1r7mr6orids9fh95y7gxhdsxjqi6nngsxxtakqaxr5no";
508 let public_key: PublicKey = str.try_into().unwrap();
509
510 let der = public_key.to_public_key_der();
511
512 assert_eq!(
513 der.as_bytes(),
514 [
515 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,
519 14, 207, 75, 171, 225, 8, 214, 123, 227, 133, 59, 15, 38, 197,
520 ]
521 )
522 }
523
524 #[cfg(all(not(target_family = "wasm"), feature = "tls"))]
525 #[test]
526 fn certificate() {
527 use rustls::SignatureAlgorithm;
528
529 let keypair = Keypair::from_secret_key(&[0; 32]);
530
531 let certified_key = keypair.to_rpk_certified_key();
532
533 assert_eq!(certified_key.key.algorithm(), SignatureAlgorithm::ED25519);
534
535 assert_eq!(
536 certified_key.end_entity_cert().unwrap().as_ref(),
537 [
538 48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 59, 106, 39, 188, 206, 182, 164, 45,
539 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, 21, 119, 29, 226, 67, 166, 58, 192,
540 72, 161, 139, 89, 218, 41,
541 ]
542 )
543 }
544
545 #[test]
546 fn invalid_key() {
547 let key = "c1bkg8tfsyy8wcedtmw4fwhdmm7bbzhgg3z58tf43m5ow8w9mbus";
548
549 assert_eq!(
550 PublicKey::try_from(key),
551 Err(PublicKeyError::InvalidEd25519PublicKey)
552 );
553 }
554}