pub mod bin_signable;
pub mod ed25519;
pub mod text_signable;
#[cfg(feature = "x25519")]
pub(crate) mod x25519;
pub use crate::seeds::Seed32;
use crate::bases::b58::ToBase58;
use crate::bases::BaseConversionError;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Error;
use std::fmt::Formatter;
use std::hash::Hash;
use std::str::FromStr;
use thiserror::Error;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum KeysAlgo {
    
    Ed25519 = 0,
    
    Schnorr = 1,
}
pub trait GetKeysAlgo: Clone + Debug + PartialEq + Eq {
    
    fn algo(&self) -> KeysAlgo;
}
#[derive(Debug, Eq, Error, PartialEq)]
pub enum SigError {
    
    #[error("Signature and pubkey are not the same algo.")]
    NotSameAlgo,
    
    #[error("Invalid signature.")]
    InvalidSig,
    
    #[error("Absence of signature.")]
    NotSig,
    
    #[error("Serialization error: {0}")]
    SerdeError(String),
}
#[derive(Debug, Eq, Error, PartialEq)]
pub enum SignError {
    
    #[error("Corrupted key pair.")]
    CorruptedKeyPair,
    
    #[error("Wrong algo.")]
    WrongAlgo,
    
    #[error("Wrong private key.")]
    WrongPrivkey,
    
    #[error("Already signed.")]
    AlreadySign,
    
    #[error("Serialization error: {0}")]
    SerdeError(String),
}
pub trait Signature: Clone + Display + Debug + PartialEq + Eq + Hash {
    
    
    
    
    
    
    
    fn from_base64(base64_string: &str) -> Result<Self, BaseConversionError>;
    
    fn to_bytes_vector(&self) -> Vec<u8>;
    
    fn to_base64(&self) -> String;
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum Sig {
    
    Ed25519(ed25519::Signature),
    
    Schnorr(),
}
impl Sig {
    
    pub fn size_in_bytes(&self) -> usize {
        match *self {
            Sig::Ed25519(_) => ed25519::SIG_SIZE_IN_BYTES + 2,
            Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
impl Display for Sig {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.to_base64())
    }
}
impl GetKeysAlgo for Sig {
    fn algo(&self) -> KeysAlgo {
        match *self {
            Sig::Ed25519(_) => KeysAlgo::Ed25519,
            Sig::Schnorr() => KeysAlgo::Schnorr,
        }
    }
}
impl Signature for Sig {
    #[cfg(not(tarpaulin_include))]
    fn from_base64(_base64_string: &str) -> Result<Self, BaseConversionError> {
        unimplemented!()
    }
    fn to_bytes_vector(&self) -> Vec<u8> {
        match *self {
            Sig::Ed25519(ed25519_sig) => ed25519_sig.to_bytes_vector(),
            Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn to_base64(&self) -> String {
        match *self {
            Sig::Ed25519(ed25519_sig) => ed25519_sig.to_base64(),
            Sig::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
pub trait PublicKey: Clone + Display + Debug + PartialEq + Eq + Hash + ToBase58 {
    
    type Signature: Signature;
    
    
    
    
    
    
    
    fn from_base58(base58_string: &str) -> Result<Self, BaseConversionError>;
    
    fn to_bytes_vector(&self) -> Vec<u8>;
    
    fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError>;
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum PubKey {
    
    Ed25519(ed25519::PublicKey),
    
    Schnorr(),
}
#[derive(Clone, Copy, Debug, Eq, Error, Hash, PartialEq)]
pub enum PubkeyFromBytesError {
    
    #[error("Invalid bytes len: expected {expected}, found {found}")]
    InvalidBytesLen {
        
        expected: usize,
        
        found: usize,
    },
    
    #[error("Invalid bytes content")]
    InvalidBytesContent,
}
impl PubKey {
    
    #[inline]
    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PubkeyFromBytesError> {
        Ok(PubKey::Ed25519(ed25519::PublicKey::try_from(bytes)?))
    }
    
    pub fn size_in_bytes(&self) -> usize {
        match *self {
            PubKey::Ed25519(_) => ed25519::PUBKEY_SIZE_IN_BYTES + 3,
            PubKey::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
impl Default for PubKey {
    fn default() -> Self {
        PubKey::Ed25519(ed25519::PublicKey::default())
    }
}
impl GetKeysAlgo for PubKey {
    fn algo(&self) -> KeysAlgo {
        match *self {
            PubKey::Ed25519(_) => KeysAlgo::Ed25519,
            PubKey::Schnorr() => KeysAlgo::Schnorr,
        }
    }
}
impl ToBase58 for PubKey {
    fn to_base58(&self) -> String {
        match *self {
            PubKey::Ed25519(ed25519_pub) => ed25519_pub.to_base58(),
            PubKey::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
impl Display for PubKey {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.to_base58())
    }
}
impl FromStr for PubKey {
    type Err = BaseConversionError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ed25519::PublicKey::from_base58(s).map(PubKey::Ed25519)
    }
}
impl PublicKey for PubKey {
    type Signature = Sig;
    #[cfg(not(tarpaulin_include))]
    fn from_base58(_base58_string: &str) -> Result<Self, BaseConversionError> {
        unimplemented!()
    }
    fn to_bytes_vector(&self) -> Vec<u8> {
        match *self {
            PubKey::Ed25519(ed25519_pubkey) => ed25519_pubkey.to_bytes_vector(),
            PubKey::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError> {
        match *self {
            PubKey::Ed25519(ed25519_pubkey) => {
                if let Sig::Ed25519(ed25519_sig) = signature {
                    ed25519_pubkey.verify(message, ed25519_sig)
                } else {
                    Err(SigError::NotSameAlgo)
                }
            }
            PubKey::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
pub trait KeyPair: Clone + Display + Debug + PartialEq + Eq {
    
    type Signator: Signator;
    
    fn generate_signator(&self) -> Self::Signator;
    
    fn public_key(&self) -> <Self::Signator as Signator>::PublicKey;
    
    fn seed(&self) -> &Seed32;
    
    fn verify(
        &self,
        message: &[u8],
        signature: &<Self::Signator as Signator>::Signature,
    ) -> Result<(), SigError>;
}
pub trait Signator: Debug {
    
    type Signature: Signature;
    
    type PublicKey: PublicKey;
    
    fn public_key(&self) -> Self::PublicKey;
    
    fn sign(&self, message: &[u8]) -> Self::Signature;
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum KeyPairEnum {
    
    Ed25519(ed25519::Ed25519KeyPair),
    
    Schnorr(),
}
impl GetKeysAlgo for KeyPairEnum {
    fn algo(&self) -> KeysAlgo {
        match *self {
            KeyPairEnum::Ed25519(_) => KeysAlgo::Ed25519,
            KeyPairEnum::Schnorr() => KeysAlgo::Schnorr,
        }
    }
}
impl Display for KeyPairEnum {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match self {
            KeyPairEnum::Ed25519(ref ed25519_keypair) => {
                write!(f, "({}, hidden)", ed25519_keypair.public_key().to_base58())
            }
            KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
impl KeyPair for KeyPairEnum {
    type Signator = SignatorEnum;
    fn generate_signator(&self) -> Self::Signator {
        match self {
            KeyPairEnum::Ed25519(ref ed25519_keypair) => {
                SignatorEnum::Ed25519(ed25519_keypair.generate_signator())
            }
            KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn public_key(&self) -> <Self::Signator as Signator>::PublicKey {
        match self {
            KeyPairEnum::Ed25519(ref ed25519_keypair) => {
                PubKey::Ed25519(ed25519_keypair.public_key())
            }
            KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn seed(&self) -> &Seed32 {
        match *self {
            KeyPairEnum::Ed25519(ref ed25519_keypair) => &ed25519_keypair.seed(),
            KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn verify(&self, message: &[u8], signature: &Sig) -> Result<(), SigError> {
        match self {
            KeyPairEnum::Ed25519(ref ed25519_keypair) => {
                if let Sig::Ed25519(ed25519_sig) = signature {
                    ed25519_keypair.verify(message, ed25519_sig)
                } else {
                    Err(SigError::NotSameAlgo)
                }
            }
            KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
#[derive(Debug)]
pub enum SignatorEnum {
    
    Ed25519(ed25519::Signator),
    
    Schnorr(),
}
impl Signator for SignatorEnum {
    type PublicKey = PubKey;
    type Signature = Sig;
    fn public_key(&self) -> Self::PublicKey {
        match self {
            SignatorEnum::Ed25519(ref ed25519_signator) => {
                PubKey::Ed25519(ed25519_signator.public_key())
            }
            SignatorEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
    fn sign(&self, message: &[u8]) -> Sig {
        match self {
            SignatorEnum::Ed25519(ref ed25519_signator) => {
                Sig::Ed25519(ed25519_signator.sign(message))
            }
            SignatorEnum::Schnorr() => panic!("Schnorr algo not yet supported !"),
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use unwrap::unwrap;
    pub fn valid_key_pair_1() -> KeyPairEnum {
        KeyPairEnum::Ed25519(ed25519::KeyPairFromSeed32Generator::generate(Seed32::new(
            [
                59u8, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101,
                50, 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41,
            ],
        )))
    }
    #[test]
    fn sig() {
        let sig_bytes = [
            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,
            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,
            0, 0, 0, 0, 0, 0, 0,
        ];
        let sig_str_b64 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==".to_owned();
        let sig = Sig::Ed25519(ed25519::Signature(sig_bytes));
        assert_eq!(sig.size_in_bytes(), ed25519::SIG_SIZE_IN_BYTES + 2);
        assert_eq!(sig_str_b64, format!("{}", sig));
        assert_eq!(KeysAlgo::Ed25519, sig.algo());
        assert_eq!(KeysAlgo::Schnorr, Sig::Schnorr().algo());
        assert_eq!(sig_bytes.to_vec(), sig.to_bytes_vector());
        assert_eq!(sig_str_b64, sig.to_base64());
    }
    #[test]
    fn public_key() {
        let ed25519_pubkey_default = ed25519::PublicKey::default();
        let pubkey_default = PubKey::Ed25519(ed25519_pubkey_default);
        let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(
            ed25519_pubkey_default.as_ref()
        )));
        let pubkey_str_b58 = "11111111111111111111111111111111".to_owned();
        assert_eq!(pubkey_default, unwrap!(PubKey::from_str(&pubkey_str_b58)));
        assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3);
        assert_eq!("11111111111111111111111111111111", &format!("{}", pubkey));
        assert_eq!(KeysAlgo::Ed25519, pubkey.algo());
        assert_eq!(KeysAlgo::Schnorr, PubKey::Schnorr().algo());
        let mut expected_vec = [0u8; 32].to_vec();
        expected_vec.push(32);
        assert_eq!(expected_vec, pubkey.to_bytes_vector());
        assert_eq!("11111111111111111111111111111111", &pubkey.to_base58());
        assert_eq!(
            Err(SigError::InvalidSig),
            pubkey.verify(
                b"message",
                &Sig::Ed25519(ed25519::Signature([
                    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, 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, 0, 0, 0, 0, 0, 0, 0,
                ]))
            )
        )
    }
    #[test]
    fn seed() {
        let seed_default = Seed32::default();
        let seed_bytes = [
            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,
            0, 0, 0, 0,
        ];
        let seed = Seed32::new(seed_bytes);
        assert_eq!(seed_default, seed);
        assert_eq!(seed_default, unwrap!(Seed32::from_base58("")));
        assert_eq!("", format!("{}", seed));
        assert_eq!("", seed.to_base58());
    }
    fn false_key_pair_ed25519() -> ed25519::Ed25519KeyPair {
        ed25519::KeyPairFromSeed32Generator::generate(Seed32::new([
            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,
            0, 0, 0, 0,
        ]))
    }
    #[test]
    fn key_pair() {
        let false_key_pair_ed25519 = false_key_pair_ed25519();
        let false_key_pair = KeyPairEnum::Ed25519(false_key_pair_ed25519.clone());
        assert_eq!(KeysAlgo::Ed25519, false_key_pair.algo());
        assert_eq!(KeysAlgo::Schnorr, KeyPairEnum::Schnorr().algo());
        assert_eq!(
            "(4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS, hidden)".to_owned(),
            format!("{}", false_key_pair)
        );
        assert_eq!(
            PubKey::Ed25519(false_key_pair_ed25519.public_key()),
            false_key_pair.public_key()
        );
        assert_eq!(
            Err(SigError::InvalidSig),
            false_key_pair.verify(
                b"message",
                &Sig::Ed25519(ed25519::Signature([
                    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, 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, 0, 0, 0, 0, 0, 0, 0
                ]))
            )
        );
    }
    #[test]
    fn key_pair_verify_wrong_sig_algo() {
        let false_key_pair_ed25519 = false_key_pair_ed25519();
        let false_key_pair = KeyPairEnum::Ed25519(false_key_pair_ed25519);
        assert_eq!(
            Err(SigError::NotSameAlgo),
            false_key_pair.verify(b"message", &Sig::Schnorr()),
        );
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn sig_schnorr_size() {
        let sig = Sig::Schnorr();
        sig.size_in_bytes();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn sig_schnorr_to_bytes() {
        let sig = Sig::Schnorr();
        sig.to_bytes_vector();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn sig_schnorr_to_base64() {
        let sig = Sig::Schnorr();
        sig.to_base64();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn pubkey_schnorr_size() {
        let pubkey = PubKey::Schnorr();
        pubkey.size_in_bytes();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn pubkey_schnorr_base58() {
        let pubkey = PubKey::Schnorr();
        pubkey.to_base58();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn pubkey_schnorr_to_bytes() {
        let pubkey = PubKey::Schnorr();
        pubkey.to_bytes_vector();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn pubkey_schnorr_verify() {
        let pubkey = PubKey::Schnorr();
        let _ = pubkey.verify(b"message", &Sig::Schnorr());
    }
    #[test]
    fn pubkey_verify_sig_wrong_algo() {
        let pubkey = PubKey::default();
        assert_eq!(
            Err(SigError::NotSameAlgo),
            pubkey.verify(b"message", &Sig::Schnorr()),
        );
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn key_pair_schnorr_display() {
        let key_pair = KeyPairEnum::Schnorr();
        format!("{}", key_pair);
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn key_pair_schnorr_generate_signator() {
        let _ = KeyPairEnum::Schnorr().generate_signator();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn key_pair_schnorr_get_pubkey() {
        let key_pair = KeyPairEnum::Schnorr();
        key_pair.public_key();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn key_pair_schnorr_get_seed() {
        let key_pair = KeyPairEnum::Schnorr();
        key_pair.seed();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn key_pair_schnorr_verify() {
        let key_pair = KeyPairEnum::Schnorr();
        let _ = key_pair.verify(b"message", &Sig::Schnorr());
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn signator_schnorr_get_pubkey() {
        let signator = SignatorEnum::Schnorr();
        signator.public_key();
    }
    #[test]
    #[should_panic(expected = "Schnorr algo not yet supported !")]
    fn signator_schnorr_sign() {
        let signator = SignatorEnum::Schnorr();
        signator.sign(b"message");
    }
    #[test]
    fn pubkey_from_bytes() {
        assert_eq!(
            Err(PubkeyFromBytesError::InvalidBytesLen {
                expected: ed25519::PUBKEY_SIZE_IN_BYTES,
                found: 34,
            }),
            PubKey::from_bytes(&[
                0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
                23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 17
            ]),
        );
    }
}