cardano_serialization_lib/chain_crypto/algorithms/
ed25519.rs

1use crate::chain_crypto::key::{
2    AsymmetricKey, AsymmetricPublicKey, PublicKeyError, SecretKeyError, SecretKeySizeStatic,
3};
4use crate::chain_crypto::sign::{
5    SignatureError, SigningAlgorithm, Verification, VerificationAlgorithm,
6};
7use cryptoxide::ed25519;
8use rand_os::rand_core::{CryptoRng, RngCore};
9
10use ed25519_bip32::XPub;
11
12/// ED25519 Signing Algorithm
13#[derive(Clone, Debug, Eq, PartialEq, Hash,  Ord, PartialOrd)]
14pub struct Ed25519;
15
16#[derive(Clone)]
17pub struct Priv([u8; ed25519::PRIVATE_KEY_LENGTH]);
18
19#[derive(Clone, PartialEq, Eq, Hash)]
20pub struct Pub(pub(crate) [u8; ed25519::PUBLIC_KEY_LENGTH]);
21
22#[derive(Clone, Hash)]
23pub struct Sig(pub(crate) [u8; ed25519::SIGNATURE_LENGTH]);
24
25impl Pub {
26    pub fn from_xpub(xpub: &XPub) -> Self {
27        let mut buf = [0; ed25519::PUBLIC_KEY_LENGTH];
28        xpub.get_without_chaincode(&mut buf);
29        Pub(buf)
30    }
31}
32
33impl AsRef<[u8]> for Priv {
34    fn as_ref(&self) -> &[u8] {
35        &self.0[..]
36    }
37}
38
39impl AsRef<[u8]> for Pub {
40    fn as_ref(&self) -> &[u8] {
41        &self.0
42    }
43}
44
45impl AsRef<[u8]> for Sig {
46    fn as_ref(&self) -> &[u8] {
47        &self.0
48    }
49}
50
51impl AsymmetricPublicKey for Ed25519 {
52    type Public = Pub;
53
54    const PUBLIC_BECH32_HRP: &'static str = "ed25519_pk";
55    const PUBLIC_KEY_SIZE: usize = ed25519::PUBLIC_KEY_LENGTH;
56
57    fn public_from_binary(data: &[u8]) -> Result<Self::Public, PublicKeyError> {
58        if data.len() != ed25519::PUBLIC_KEY_LENGTH {
59            return Err(PublicKeyError::SizeInvalid);
60        }
61        let mut buf = [0; ed25519::PUBLIC_KEY_LENGTH];
62        buf[0..ed25519::PUBLIC_KEY_LENGTH].clone_from_slice(data);
63        Ok(Pub(buf))
64    }
65}
66
67impl AsymmetricKey for Ed25519 {
68    type Secret = Priv;
69    type PubAlg = Ed25519;
70
71    const SECRET_BECH32_HRP: &'static str = "ed25519_sk";
72
73    fn generate<T: RngCore + CryptoRng>(mut rng: T) -> Self::Secret {
74        let mut priv_bytes = [0u8; ed25519::PRIVATE_KEY_LENGTH];
75        rng.fill_bytes(&mut priv_bytes);
76        Priv(priv_bytes)
77    }
78
79    fn compute_public(key: &Self::Secret) -> <Self::PubAlg as AsymmetricPublicKey>::Public {
80        let (_, pk) = ed25519::keypair(&key.0);
81        Pub(pk)
82    }
83
84    fn secret_from_binary(data: &[u8]) -> Result<Self::Secret, SecretKeyError> {
85        if data.len() != ed25519::PRIVATE_KEY_LENGTH {
86            return Err(SecretKeyError::SizeInvalid);
87        }
88        let mut buf = [0; ed25519::PRIVATE_KEY_LENGTH];
89        buf[0..ed25519::PRIVATE_KEY_LENGTH].clone_from_slice(data);
90        Ok(Priv(buf))
91    }
92}
93
94impl SecretKeySizeStatic for Ed25519 {
95    const SECRET_KEY_SIZE: usize = ed25519::PRIVATE_KEY_LENGTH;
96}
97
98impl VerificationAlgorithm for Ed25519 {
99    type Signature = Sig;
100
101    const SIGNATURE_SIZE: usize = ed25519::SIGNATURE_LENGTH;
102    const SIGNATURE_BECH32_HRP: &'static str = "ed25519_sig";
103
104    fn signature_from_bytes(data: &[u8]) -> Result<Self::Signature, SignatureError> {
105        if data.len() != ed25519::SIGNATURE_LENGTH {
106            return Err(SignatureError::SizeInvalid {
107                expected: ed25519::SIGNATURE_LENGTH,
108                got: data.len(),
109            });
110        }
111        let mut buf = [0; ed25519::SIGNATURE_LENGTH];
112        buf[0..ed25519::SIGNATURE_LENGTH].clone_from_slice(data);
113        Ok(Sig(buf))
114    }
115
116    fn verify_bytes(
117        pubkey: &Self::Public,
118        signature: &Self::Signature,
119        msg: &[u8],
120    ) -> Verification {
121        ed25519::verify(msg, &pubkey.0, &signature.0).into()
122    }
123}
124
125impl SigningAlgorithm for Ed25519 {
126    fn sign(key: &Self::Secret, msg: &[u8]) -> Sig {
127        let (sk, _) = ed25519::keypair(&key.0);
128        Sig(ed25519::signature(msg, &sk))
129    }
130}
131
132#[cfg(test)]
133mod test {
134    use super::*;
135
136    use crate::chain_crypto::key::KeyPair;
137    use crate::chain_crypto::sign::test::{keypair_signing_ko, keypair_signing_ok};
138
139    #[quickcheck]
140    fn sign_ok(input: (KeyPair<Ed25519>, Vec<u8>)) -> bool {
141        keypair_signing_ok(input)
142    }
143
144    #[quickcheck]
145    fn sign_ko(input: (KeyPair<Ed25519>, KeyPair<Ed25519>, Vec<u8>)) -> bool {
146        keypair_signing_ko(input)
147    }
148}