cardano_serialization_lib/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_os::rand_core::{CryptoRng, RngCore};
9
10use ed25519_bip32::XPub;
11
12#[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}