cardano_serialization_lib/chain_crypto/algorithms/
ed25519_extended.rs

1use crate::chain_crypto::key::{
2    AsymmetricKey, AsymmetricPublicKey, SecretKeyError, SecretKeySizeStatic,
3};
4use crate::chain_crypto::sign::SigningAlgorithm;
5
6use super::ed25519 as ei;
7
8use cryptoxide::ed25519;
9use rand_os::rand_core::{CryptoRng, RngCore};
10
11use ed25519_bip32::{XPrv, XPRV_SIZE};
12
13/// ED25519 Signing Algorithm with extended secret key
14pub struct Ed25519Extended;
15
16#[derive(Clone)]
17pub struct ExtendedPriv([u8; ed25519::EXTENDED_KEY_LENGTH]);
18
19impl AsRef<[u8]> for ExtendedPriv {
20    fn as_ref(&self) -> &[u8] {
21        &self.0[..]
22    }
23}
24
25impl ExtendedPriv {
26    pub fn from_xprv(xprv: &XPrv) -> Self {
27        let mut buf = [0; ed25519::EXTENDED_KEY_LENGTH];
28        xprv.get_extended_mut(&mut buf);
29        ExtendedPriv(buf)
30    }
31}
32
33impl AsymmetricKey for Ed25519Extended {
34    type Secret = ExtendedPriv;
35    type PubAlg = ei::Ed25519;
36
37    const SECRET_BECH32_HRP: &'static str = "ed25519e_sk";
38
39    fn generate<T: RngCore + CryptoRng>(mut rng: T) -> Self::Secret {
40        let mut priv_bytes = [0u8; XPRV_SIZE];
41        rng.fill_bytes(&mut priv_bytes);
42        let xprv = XPrv::normalize_bytes_force3rd(priv_bytes);
43
44        let mut out = [0u8; ed25519::EXTENDED_KEY_LENGTH];
45        xprv.get_extended_mut(&mut out);
46        ExtendedPriv(out)
47    }
48
49    fn compute_public(key: &Self::Secret) -> <Self::PubAlg as AsymmetricPublicKey>::Public {
50        let pk = ed25519::extended_to_public(&key.0);
51        ei::Pub(pk)
52    }
53
54    fn secret_from_binary(data: &[u8]) -> Result<Self::Secret, SecretKeyError> {
55        if data.len() != ed25519::EXTENDED_KEY_LENGTH {
56            return Err(SecretKeyError::SizeInvalid);
57        }
58        let mut buf = [0; ed25519::EXTENDED_KEY_LENGTH];
59        buf.clone_from_slice(data);
60        // TODO structure check
61        Ok(ExtendedPriv(buf))
62    }
63}
64
65impl SecretKeySizeStatic for Ed25519Extended {
66    const SECRET_KEY_SIZE: usize = ed25519::PRIVATE_KEY_LENGTH;
67}
68
69impl SigningAlgorithm for Ed25519Extended {
70    fn sign(key: &Self::Secret, msg: &[u8]) -> ei::Sig {
71        ei::Sig(ed25519::signature_extended(msg, &key.0))
72    }
73}
74
75#[cfg(test)]
76mod test {
77    use super::*;
78
79    use crate::chain_crypto::key::KeyPair;
80    use crate::chain_crypto::sign::test::{keypair_signing_ko, keypair_signing_ok};
81
82    #[quickcheck]
83    fn sign_ok(input: (KeyPair<Ed25519Extended>, Vec<u8>)) -> bool {
84        keypair_signing_ok(input)
85    }
86
87    #[quickcheck]
88    fn sign_ko(input: (KeyPair<Ed25519Extended>, KeyPair<Ed25519Extended>, Vec<u8>)) -> bool {
89        keypair_signing_ko(input)
90    }
91}