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