1pub mod bin_signable;
52pub mod ed25519;
53pub mod text_signable;
54#[cfg(feature = "x25519")]
55pub(crate) mod x25519;
56
57pub use crate::seeds::Seed32;
58
59use crate::bases::b58::ToBase58;
60use crate::bases::BaseConversionError;
61use serde::{Deserialize, Serialize};
62use std::convert::TryFrom;
63use std::fmt::Debug;
64use std::fmt::Display;
65use std::fmt::Error;
66use std::fmt::Formatter;
67use std::hash::Hash;
68use std::str::FromStr;
69use thiserror::Error;
70
71#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
73pub enum KeysAlgo {
74 Ed25519 = 0,
76 Bip32Ed25519 = 1,
78}
79
80#[derive(Clone, Copy, Debug, Error)]
81#[error("unknown algorithm")]
82pub(crate) struct UnknownAlgo;
84
85#[allow(dead_code)]
86impl KeysAlgo {
87 pub(crate) fn from_u8(u8_: u8) -> Result<KeysAlgo, UnknownAlgo> {
88 match u8_ {
89 0 => Ok(KeysAlgo::Ed25519),
90 1 => Ok(KeysAlgo::Bip32Ed25519),
91 _ => Err(UnknownAlgo),
92 }
93 }
94 pub(crate) fn to_u8(self) -> u8 {
95 match self {
96 KeysAlgo::Ed25519 => 0,
97 KeysAlgo::Bip32Ed25519 => 1,
98 }
99 }
100}
101
102pub trait GetKeysAlgo: Clone + Debug + PartialEq + Eq {
104 fn algo(&self) -> KeysAlgo;
106}
107
108#[derive(Debug, Eq, Error, PartialEq)]
110pub enum SigError {
111 #[error("Signature and pubkey are not the same algo.")]
113 NotSameAlgo,
114 #[error("Invalid signature.")]
116 InvalidSig,
117 #[error("Absence of signature.")]
119 NotSig,
120 #[error("Serialization error: {0}")]
122 SerdeError(String),
123}
124
125#[derive(Debug, Eq, Error, PartialEq)]
127pub enum SignError {
128 #[error("Corrupted key pair.")]
130 CorruptedKeyPair,
131 #[error("Wrong algo.")]
133 WrongAlgo,
134 #[error("Wrong private key.")]
136 WrongPrivkey,
137 #[error("Already signed.")]
139 AlreadySign,
140 #[error("Serialization error: {0}")]
142 SerdeError(String),
143}
144
145pub trait Signature: Clone + Display + Debug + PartialEq + Eq + Hash {
156 fn from_base64(base64_string: &str) -> Result<Self, BaseConversionError>;
164
165 fn to_bytes_vector(&self) -> Vec<u8>;
167
168 fn to_base64(&self) -> String;
170}
171
172#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
174pub enum Sig {
175 Ed25519(ed25519::Signature),
177 Schnorr(),
179}
180
181impl Sig {
182 pub fn size_in_bytes(&self) -> usize {
184 match *self {
185 Sig::Ed25519(_) => ed25519::SIG_SIZE_IN_BYTES + 2,
186 Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
187 }
188 }
189}
190
191impl Display for Sig {
192 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
193 write!(f, "{}", self.to_base64())
194 }
195}
196
197impl GetKeysAlgo for Sig {
198 fn algo(&self) -> KeysAlgo {
199 match *self {
200 Sig::Ed25519(_) => KeysAlgo::Ed25519,
201 Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
202 }
203 }
204}
205
206impl Signature for Sig {
207 #[cfg(not(tarpaulin_include))]
208 fn from_base64(_base64_string: &str) -> Result<Self, BaseConversionError> {
209 unimplemented!()
210 }
211 fn to_bytes_vector(&self) -> Vec<u8> {
212 match *self {
213 Sig::Ed25519(ed25519_sig) => ed25519_sig.to_bytes_vector(),
214 Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
215 }
216 }
217 fn to_base64(&self) -> String {
218 match *self {
219 Sig::Ed25519(ed25519_sig) => ed25519_sig.to_base64(),
220 Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
221 }
222 }
223}
224
225pub trait PublicKey: Clone + Display + Debug + PartialEq + Eq + Hash + ToBase58 {
235 type Signature: Signature;
237
238 fn from_base58(base58_string: &str) -> Result<Self, BaseConversionError>;
246
247 fn to_bytes_vector(&self) -> Vec<u8>;
249
250 fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError>;
252}
253
254#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
256pub enum PubKeyEnum {
257 Ed25519(ed25519::PublicKey),
259}
260
261#[derive(Clone, Copy, Debug, Eq, Error, Hash, PartialEq)]
262pub enum PubKeyFromBytesError {
264 #[error("Invalid bytes len: expected {expected}, found {found}")]
266 InvalidBytesLen {
267 expected: usize,
269 found: usize,
271 },
272 #[error("Invalid bytes content")]
274 InvalidBytesContent,
275}
276
277impl PubKeyEnum {
278 #[inline]
280 pub fn from_bytes(bytes: &[u8]) -> Result<Self, PubKeyFromBytesError> {
281 Ok(PubKeyEnum::Ed25519(ed25519::PublicKey::try_from(bytes)?))
282 }
283 pub fn size_in_bytes(&self) -> usize {
285 match *self {
286 PubKeyEnum::Ed25519(_) => ed25519::PUBKEY_SIZE_IN_BYTES + 3,
287 }
288 }
289}
290
291impl Default for PubKeyEnum {
292 fn default() -> Self {
293 PubKeyEnum::Ed25519(ed25519::PublicKey::default())
294 }
295}
296
297impl GetKeysAlgo for PubKeyEnum {
298 fn algo(&self) -> KeysAlgo {
299 match *self {
300 PubKeyEnum::Ed25519(_) => KeysAlgo::Ed25519,
301 }
302 }
303}
304
305impl ToBase58 for PubKeyEnum {
306 fn to_base58(&self) -> String {
307 match *self {
308 PubKeyEnum::Ed25519(ed25519_pub) => ed25519_pub.to_base58(),
309 }
310 }
311}
312
313impl Display for PubKeyEnum {
314 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
315 write!(f, "{}", self.to_base58())
316 }
317}
318
319impl FromStr for PubKeyEnum {
320 type Err = BaseConversionError;
321
322 fn from_str(s: &str) -> Result<Self, Self::Err> {
323 ed25519::PublicKey::from_base58(s).map(PubKeyEnum::Ed25519)
324 }
325}
326
327impl PublicKey for PubKeyEnum {
328 type Signature = Sig;
329
330 #[cfg(not(tarpaulin_include))]
331 fn from_base58(_base58_string: &str) -> Result<Self, BaseConversionError> {
332 unimplemented!()
333 }
334 fn to_bytes_vector(&self) -> Vec<u8> {
335 match *self {
336 PubKeyEnum::Ed25519(ed25519_pubkey) => ed25519_pubkey.to_bytes_vector(),
337 }
338 }
339 fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError> {
340 match *self {
341 PubKeyEnum::Ed25519(ed25519_pubkey) => {
342 if let Sig::Ed25519(ed25519_sig) = signature {
343 ed25519_pubkey.verify(message, ed25519_sig)
344 } else {
345 Err(SigError::NotSameAlgo)
346 }
347 }
348 }
349 }
350}
351
352pub(crate) mod inner {
353 #[doc(hidden)]
354 pub trait KeyPairInner {
355 fn scalar_bytes_without_normalization(&self) -> [u8; 32];
356 }
357}
358
359pub trait KeyPair: Clone + Display + Debug + inner::KeyPairInner + PartialEq + Eq {
361 type Seed: AsRef<[u8]>;
363 type Signator: Signator;
365
366 fn generate_signator(&self) -> Self::Signator;
368
369 fn from_seed(seed: Self::Seed) -> Self;
371
372 fn public_key(&self) -> <Self::Signator as Signator>::PublicKey;
374
375 fn verify(
377 &self,
378 message: &[u8],
379 signature: &<<Self::Signator as Signator>::PublicKey as PublicKey>::Signature,
380 ) -> Result<(), SigError>;
381
382 fn upcast(self) -> KeyPairEnum;
384}
385
386pub trait Signator: Debug {
388 type PublicKey: PublicKey;
390
391 fn public_key(&self) -> Self::PublicKey;
393
394 fn sign(&self, message: &[u8]) -> <Self::PublicKey as PublicKey>::Signature;
396}
397
398#[derive(Clone, Debug, Eq, PartialEq)]
400#[non_exhaustive]
401pub enum KeyPairEnum {
402 Ed25519(ed25519::Ed25519KeyPair),
404 #[cfg(feature = "bip32-ed25519")]
405 Bip32Ed25519(ed25519::bip32::KeyPair),
407}
408
409impl GetKeysAlgo for KeyPairEnum {
410 fn algo(&self) -> KeysAlgo {
411 match *self {
412 KeyPairEnum::Ed25519(_) => KeysAlgo::Ed25519,
413 #[cfg(feature = "bip32-ed25519")]
414 KeyPairEnum::Bip32Ed25519(_) => KeysAlgo::Bip32Ed25519,
415 }
416 }
417}
418
419impl Display for KeyPairEnum {
420 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
421 match self {
422 KeyPairEnum::Ed25519(ref ed25519_keypair) => {
423 write!(f, "{}", ed25519_keypair)
424 }
425 #[cfg(feature = "bip32-ed25519")]
426 KeyPairEnum::Bip32Ed25519(ref keypair) => {
427 write!(f, "{}", keypair)
428 }
429 }
430 }
431}
432
433impl inner::KeyPairInner for KeyPairEnum {
434 fn scalar_bytes_without_normalization(&self) -> [u8; 32] {
435 match self {
436 KeyPairEnum::Ed25519(ref ed25519_keypair) => {
437 ed25519_keypair.scalar_bytes_without_normalization()
438 }
439 #[cfg(feature = "bip32-ed25519")]
440 KeyPairEnum::Bip32Ed25519(ref keypair) => keypair.scalar_bytes_without_normalization(),
441 }
442 }
443}
444
445impl KeyPair for KeyPairEnum {
446 type Seed = Seed32;
447 type Signator = SignatorEnum;
448
449 fn generate_signator(&self) -> Self::Signator {
450 match self {
451 KeyPairEnum::Ed25519(ref ed25519_keypair) => {
452 SignatorEnum::Ed25519(ed25519_keypair.generate_signator())
453 }
454 #[cfg(feature = "bip32-ed25519")]
455 KeyPairEnum::Bip32Ed25519(ref keypair) => {
456 SignatorEnum::Bip32Ed25519(keypair.generate_signator())
457 }
458 }
459 }
460 fn from_seed(_: Self::Seed) -> Self {
461 unimplemented!()
462 }
463 fn public_key(&self) -> <Self::Signator as Signator>::PublicKey {
464 match self {
465 KeyPairEnum::Ed25519(ref ed25519_keypair) => {
466 PubKeyEnum::Ed25519(ed25519_keypair.public_key())
467 }
468 #[cfg(feature = "bip32-ed25519")]
469 KeyPairEnum::Bip32Ed25519(ref keypair) => PubKeyEnum::Ed25519(keypair.public_key()),
470 }
471 }
472 fn verify(&self, message: &[u8], signature: &Sig) -> Result<(), SigError> {
473 match self {
474 KeyPairEnum::Ed25519(ref keypair) => {
475 if let Sig::Ed25519(sig) = signature {
476 keypair.verify(message, sig)
477 } else {
478 Err(SigError::NotSameAlgo)
479 }
480 }
481 #[cfg(feature = "bip32-ed25519")]
482 KeyPairEnum::Bip32Ed25519(ref keypair) => {
483 if let Sig::Ed25519(sig) = signature {
484 keypair.verify(message, sig)
485 } else {
486 Err(SigError::NotSameAlgo)
487 }
488 }
489 }
490 }
491 #[inline(always)]
492 fn upcast(self) -> KeyPairEnum {
493 self
494 }
495}
496
497#[derive(Debug)]
499pub enum SignatorEnum {
500 Ed25519(ed25519::Signator),
502 Schnorr(),
504 #[cfg(feature = "bip32-ed25519")]
505 Bip32Ed25519(ed25519::bip32::Signator),
507}
508
509impl Signator for SignatorEnum {
510 type PublicKey = PubKeyEnum;
511
512 fn public_key(&self) -> Self::PublicKey {
513 match self {
514 SignatorEnum::Ed25519(ref ed25519_signator) => {
515 PubKeyEnum::Ed25519(ed25519_signator.public_key())
516 }
517 SignatorEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
518 #[cfg(feature = "bip32-ed25519")]
519 SignatorEnum::Bip32Ed25519(ref signator) => PubKeyEnum::Ed25519(signator.public_key()),
520 }
521 }
522
523 fn sign(&self, message: &[u8]) -> Sig {
524 match self {
525 SignatorEnum::Ed25519(ref ed25519_signator) => {
526 Sig::Ed25519(ed25519_signator.sign(message))
527 }
528 SignatorEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
529 #[cfg(feature = "bip32-ed25519")]
530 SignatorEnum::Bip32Ed25519(ref signator) => Sig::Ed25519(signator.sign(message)),
531 }
532 }
533}
534
535#[cfg(test)]
536mod tests {
537
538 use super::*;
539 use unwrap::unwrap;
540
541 pub fn valid_key_pair_1() -> KeyPairEnum {
542 KeyPairEnum::Ed25519(ed25519::KeyPairFromSeed32Generator::generate(Seed32::new(
543 [
544 59u8, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101,
545 50, 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41,
546 ],
547 )))
548 }
549
550 #[test]
551 fn sig() {
552 let sig_bytes = [
553 0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
554 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
555 0, 0, 0, 0, 0, 0, 0,
556 ];
557 let sig_str_b64 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==".to_owned();
558 let sig = Sig::Ed25519(ed25519::Signature(sig_bytes));
559
560 assert_eq!(sig.size_in_bytes(), ed25519::SIG_SIZE_IN_BYTES + 2);
561 assert_eq!(sig_str_b64, format!("{}", sig));
562
563 assert_eq!(KeysAlgo::Ed25519, sig.algo());
564
565 assert_eq!(sig_bytes.to_vec(), sig.to_bytes_vector());
566
567 assert_eq!(sig_str_b64, sig.to_base64());
568 }
569
570 #[test]
571 fn public_key() {
572 let ed25519_pubkey_default = ed25519::PublicKey::default();
573 let pubkey_default = PubKeyEnum::Ed25519(ed25519_pubkey_default);
574 let pubkey = PubKeyEnum::Ed25519(unwrap!(ed25519::PublicKey::try_from(
575 ed25519_pubkey_default.as_ref()
576 )));
577
578 let pubkey_str_b58 = "11111111111111111111111111111111".to_owned();
579 assert_eq!(
580 pubkey_default,
581 unwrap!(PubKeyEnum::from_str(&pubkey_str_b58))
582 );
583
584 assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3);
585 assert_eq!("11111111111111111111111111111111", &format!("{}", pubkey));
586
587 assert_eq!(KeysAlgo::Ed25519, pubkey.algo());
588
589 let mut expected_vec = [0u8; 32].to_vec();
590 expected_vec.push(32);
591 assert_eq!(expected_vec, pubkey.to_bytes_vector());
592
593 assert_eq!("11111111111111111111111111111111", &pubkey.to_base58());
594
595 assert_eq!(
596 Err(SigError::InvalidSig),
597 pubkey.verify(
598 b"message",
599 &Sig::Ed25519(ed25519::Signature([
600 0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
601 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
602 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
603 ]))
604 )
605 )
606 }
607
608 #[test]
609 fn seed() {
610 let seed_default = Seed32::default();
611 let seed_bytes = [
612 0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
613 0, 0, 0, 0,
614 ];
615
616 let seed = Seed32::new(seed_bytes);
617
618 assert_eq!(seed_default, seed);
619 assert_eq!(seed_default, unwrap!(Seed32::from_base58("")));
620
621 assert_eq!("", format!("{}", seed));
622
623 assert_eq!("", seed.to_base58());
624 }
625
626 fn false_key_pair_ed25519() -> ed25519::Ed25519KeyPair {
627 ed25519::KeyPairFromSeed32Generator::generate(Seed32::new([
628 0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
629 0, 0, 0, 0,
630 ]))
631 }
632
633 #[test]
634 fn key_pair() {
635 let false_key_pair_ed25519 = false_key_pair_ed25519();
636 let false_key_pair = KeyPairEnum::Ed25519(false_key_pair_ed25519.clone());
637
638 assert_eq!(KeysAlgo::Ed25519, false_key_pair.algo());
639 assert_eq!(
640 "(4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS, hidden)".to_owned(),
641 format!("{}", false_key_pair)
642 );
643 assert_eq!(
644 PubKeyEnum::Ed25519(false_key_pair_ed25519.public_key()),
645 false_key_pair.public_key()
646 );
647 assert_eq!(
648 Err(SigError::InvalidSig),
649 false_key_pair.verify(
650 b"message",
651 &Sig::Ed25519(ed25519::Signature([
652 0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
653 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
654 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
655 ]))
656 )
657 );
658 }
659
660 #[test]
661 fn key_pair_verify_wrong_sig_algo() {
662 let false_key_pair_ed25519 = false_key_pair_ed25519();
663 let false_key_pair = KeyPairEnum::Ed25519(false_key_pair_ed25519);
664 assert_eq!(
665 Err(SigError::NotSameAlgo),
666 false_key_pair.verify(b"message", &Sig::Schnorr()),
667 );
668 }
669
670 #[test]
671 fn pubkey_verify_sig_wrong_algo() {
672 let pubkey = PubKeyEnum::default();
673 assert_eq!(
674 Err(SigError::NotSameAlgo),
675 pubkey.verify(b"message", &Sig::Schnorr()),
676 );
677 }
678
679 #[test]
680 #[should_panic(expected = "Schnorr algo not yet supported !")]
681 fn signator_schnorr_get_pubkey() {
682 let signator = SignatorEnum::Schnorr();
683 signator.public_key();
684 }
685
686 #[test]
687 #[should_panic(expected = "Schnorr algo not yet supported !")]
688 fn signator_schnorr_sign() {
689 let signator = SignatorEnum::Schnorr();
690 signator.sign(b"message");
691 }
692
693 #[test]
694 fn pubkey_from_bytes() {
695 assert_eq!(
696 Err(PubKeyFromBytesError::InvalidBytesLen {
697 expected: ed25519::PUBKEY_SIZE_IN_BYTES,
698 found: 34,
699 }),
700 PubKeyEnum::from_bytes(&[
701 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
702 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 17
703 ]),
704 );
705 }
706}