dup_crypto/
keys.rs

1//  Copyright (C) 2020 Éloïs SANCHEZ.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16//! Provide wrappers around public keys, private keys and signatures.
17//!
18//! - Keys can be converted to/from Base58 string format.
19//! - Signatures can be converted to/from Base64 string format.
20//!
21//! # Generate and use ed25519 key-pair
22//!
23//! ```ignore
24//! use dup_crypto::keys::{KeyPair, PublicKey, Signator, Signature};
25//! use dup_crypto::keys::ed25519::{KeyPairFromSaltedPasswordGenerator, SaltedPassword};
26//!
27//! let generator = KeyPairFromSaltedPasswordGenerator::generate;
28//!
29//! let keypair = generator.generate(SaltedPassword::new(
30//!     "salt".to_owned(),
31//!     "password".to_owned(),
32//! ));
33//!
34//! let signator = keypair.generate_signator();
35//!
36//! let message = "Hello, world!";
37//!
38//! let signature = signator.sign(&message.as_bytes());
39//!
40//! assert!(keypair.public_key().verify(&message.as_bytes(), &signature).is_ok());
41//! ```
42//!
43//! # Format
44//!
45//! - Base58 use the following alphabet :
46//! `123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`
47//! - Base64 use the following alphabet :
48//! `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`
49//! with `=` as padding character.
50
51pub 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/// Cryptographic keys algorithms list
72#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
73pub enum KeysAlgo {
74    /// Ed25519 algorithm
75    Ed25519 = 0,
76    /// BIP32-Ed25519 algorithm
77    Bip32Ed25519 = 1,
78}
79
80#[derive(Clone, Copy, Debug, Error)]
81#[error("unknown algorithm")]
82/// Unknown algorithm
83pub(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
102/// Get the cryptographic algorithm.
103pub trait GetKeysAlgo: Clone + Debug + PartialEq + Eq {
104    /// Get the cryptographic algorithm.
105    fn algo(&self) -> KeysAlgo;
106}
107
108/// Errors enumeration for signature verification.
109#[derive(Debug, Eq, Error, PartialEq)]
110pub enum SigError {
111    /// Signature and pubkey are not the same algo
112    #[error("Signature and pubkey are not the same algo.")]
113    NotSameAlgo,
114    /// Invalid signature
115    #[error("Invalid signature.")]
116    InvalidSig,
117    /// Absence of signature
118    #[error("Absence of signature.")]
119    NotSig,
120    /// Serialization error
121    #[error("Serialization error: {0}")]
122    SerdeError(String),
123}
124
125/// SignError
126#[derive(Debug, Eq, Error, PartialEq)]
127pub enum SignError {
128    /// Corrupted key pair
129    #[error("Corrupted key pair.")]
130    CorruptedKeyPair,
131    /// WrongAlgo
132    #[error("Wrong algo.")]
133    WrongAlgo,
134    /// WrongPrivkey
135    #[error("Wrong private key.")]
136    WrongPrivkey,
137    /// AlreadySign
138    #[error("Already signed.")]
139    AlreadySign,
140    /// Serialization error
141    #[error("Serialization error: {0}")]
142    SerdeError(String),
143}
144
145/// Define the operations that can be performed on a cryptographic signature.
146///
147/// A signature can be converted from/to Base64 format.
148/// When converted back and forth the value should be the same.
149///
150/// A signature can be made with a [`PrivateKey`]
151/// and a message, and verified with the associated [`PublicKey`].
152///
153/// [`PrivateKey`]: trait.PrivateKey.html
154/// [`PublicKey`]: trait.PublicKey.html
155pub trait Signature: Clone + Display + Debug + PartialEq + Eq + Hash {
156    /// Create a `Signature` from a Base64 string.
157    ///
158    /// The Base64 string should contains only valid Base64 characters
159    /// and have a correct length (64 bytes when converted). If it's not the case,
160    /// a [`BaseConvertionError`] is returned with the corresponding variant.
161    ///
162    /// [`BaseConvertionError`]: enum.BaseConvertionError.html
163    fn from_base64(base64_string: &str) -> Result<Self, BaseConversionError>;
164
165    /// Convert Signature into butes vector
166    fn to_bytes_vector(&self) -> Vec<u8>;
167
168    /// Encode the signature into Base64 string format.
169    fn to_base64(&self) -> String;
170}
171
172/// Store a cryptographic signature.
173#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
174pub enum Sig {
175    /// Store a ed25519 Signature
176    Ed25519(ed25519::Signature),
177    /// Store a Schnorr Signature
178    Schnorr(),
179}
180
181impl Sig {
182    /// Get Sig size in bytes
183    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
225/// Define the operations that can be performed on a cryptographic public key.
226///
227/// A `PublicKey` can be converted from/to Base64 format.
228/// When converted back and forth the value should be the same.
229///
230/// A `PublicKey` is used to verify the signature of a message
231/// with the associated [`PrivateKey`].
232///
233/// [`PrivateKey`]: trait.PrivateKey.html
234pub trait PublicKey: Clone + Display + Debug + PartialEq + Eq + Hash + ToBase58 {
235    /// Signature type of associated cryptosystem.
236    type Signature: Signature;
237
238    /// Create a PublicKey from a Base58 string.
239    ///
240    /// The Base58 string should contains only valid Base58 characters
241    /// and have a correct length. If it's not the case,
242    /// a [`BaseConvertionError`] is returned with the corresponding variant.
243    ///
244    /// [`BaseConvertionError`]: enum.BaseConvertionError.html
245    fn from_base58(base58_string: &str) -> Result<Self, BaseConversionError>;
246
247    /// Convert into bytes vector
248    fn to_bytes_vector(&self) -> Vec<u8>;
249
250    /// Verify a signature with this public key.
251    fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError>;
252}
253
254/// Store a cryptographic public key.
255#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
256pub enum PubKeyEnum {
257    /// Store a ed25519 public key.
258    Ed25519(ed25519::PublicKey),
259}
260
261#[derive(Clone, Copy, Debug, Eq, Error, Hash, PartialEq)]
262/// Error when parsing pubkey bytes
263pub enum PubKeyFromBytesError {
264    /// Invalid bytes length
265    #[error("Invalid bytes len: expected {expected}, found {found}")]
266    InvalidBytesLen {
267        /// Expected length
268        expected: usize,
269        /// Found length
270        found: usize,
271    },
272    /// Invalid bytes content
273    #[error("Invalid bytes content")]
274    InvalidBytesContent,
275}
276
277impl PubKeyEnum {
278    /// Create pubkey from bytes
279    #[inline]
280    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PubKeyFromBytesError> {
281        Ok(PubKeyEnum::Ed25519(ed25519::PublicKey::try_from(bytes)?))
282    }
283    /// Compute PubKey size in bytes
284    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
359/// Define the operations that can be performed on a cryptographic key pair.
360pub trait KeyPair: Clone + Display + Debug + inner::KeyPairInner + PartialEq + Eq {
361    /// Seed
362    type Seed: AsRef<[u8]>;
363    /// Signator type of associated cryptosystem.
364    type Signator: Signator;
365
366    /// Generate signator.
367    fn generate_signator(&self) -> Self::Signator;
368
369    /// Generate keypair from seed
370    fn from_seed(seed: Self::Seed) -> Self;
371
372    /// Get `PublicKey`
373    fn public_key(&self) -> <Self::Signator as Signator>::PublicKey;
374
375    /// Verify a signature with public key.
376    fn verify(
377        &self,
378        message: &[u8],
379        signature: &<<Self::Signator as Signator>::PublicKey as PublicKey>::Signature,
380    ) -> Result<(), SigError>;
381
382    /// Upcast to KeyPairEnum
383    fn upcast(self) -> KeyPairEnum;
384}
385
386/// Define the operations that can be performed on a cryptographic signator.
387pub trait Signator: Debug {
388    /// PublicKey type of associated cryptosystem.
389    type PublicKey: PublicKey;
390
391    /// Get `PublicKey`
392    fn public_key(&self) -> Self::PublicKey;
393
394    /// Sign a message with private key encasuled in signator.
395    fn sign(&self, message: &[u8]) -> <Self::PublicKey as PublicKey>::Signature;
396}
397
398/// Store a cryptographic key pair.
399#[derive(Clone, Debug, Eq, PartialEq)]
400#[non_exhaustive]
401pub enum KeyPairEnum {
402    /// Store a ed25519 key pair.
403    Ed25519(ed25519::Ed25519KeyPair),
404    #[cfg(feature = "bip32-ed25519")]
405    /// Store a BIP32-ed25519 key pair.
406    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/// Store a cryptographic signator.
498#[derive(Debug)]
499pub enum SignatorEnum {
500    /// Store a ed25519 signator.
501    Ed25519(ed25519::Signator),
502    /// Store a Schnorr signator.
503    Schnorr(),
504    #[cfg(feature = "bip32-ed25519")]
505    /// Store a BIP32-Ed25519 signator.
506    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}