cardano_sdk/crypto/
key.rs

1//! Cardano Crypto Keys
2//!
3//! Secret keys:
4//!
5//! * HDKey : Hierarchical Deterministic
6//! * ExtendedEd25519Key : Extended ED25519 key
7//! * Ed25519Key : Standard Ed25519 key
8//!
9//! Public keys:
10//!
11//! * HDPublicKey
12//! * Ed25519PublicKey
13//! * Ed25519PublicKey
14//!
15//!
16//! ```none
17//! HDKey --------------- .to_public() -----> HDPublicKey
18//!   |                                          |
19//!  .strip_hd()                             .strip_hd()
20//!   |                                          |
21//!   ↓                                          ↓
22//! ExtendedEd25519Key -- .to_public() ---> Ed25519PublicKey
23//!                                              ^
24//!                                              |
25//! Ed25519Key ---------- .to_public() ---------/
26//! ```
27//!
28use bech32::{ToBase32, Variant};
29use cbored::CborRepr;
30use cryptoxide::ed25519;
31use cryptoxide::{hashing::blake2b_224, hmac::Hmac, pbkdf2::pbkdf2, sha2::Sha512};
32use ed25519_bip32::{DerivationScheme, XPrv, XPub, XPRV_SIZE};
33use std::fmt;
34
35use crate::chain::{Ed25519KeyHash, TxHash, VkeyWitness};
36
37/// A Secret HD (Hierarchical Deterministic) key
38///
39/// It can turns into a `ExtendedEd25519Key` by using the `.strip_hd()` method
40#[derive(Clone)]
41pub struct HDKey(XPrv);
42
43/// A Extended ED25519 Secret key
44///
45/// It can turns into a `Ed25519PublicKey` by using the `.to_public()` method
46#[derive(Clone)]
47pub struct Ed25519ExtendedKey([u8; 64]);
48
49/// A ED25519 Secret key
50///
51/// Note: the inner format is actually an ED25519 keypair
52///
53/// It can turns into a `Ed25519PublicKey` by using the `.to_public()` method
54#[derive(Clone)]
55pub struct Ed25519Key([u8; 64]);
56
57#[derive(Clone, CborRepr, PartialEq, Eq)]
58#[cborrepr(structure = "flat")]
59pub struct Ed25519Signature([u8; 64]);
60
61impl fmt::Debug for Ed25519Signature {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "ed25519sig-{}", hex::encode(&self.0))
64    }
65}
66
67impl fmt::Display for Ed25519Signature {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        write!(f, "ed25519sig-{}", hex::encode(&self.0))
70    }
71}
72
73/// A Public HD (Hierarchical Deterministic) key
74///
75/// It can turns into a `Ed25519PublicKey` by using the `.strip_hd()` method
76#[derive(Clone, PartialEq, Eq, Hash)]
77pub struct HDPublicKey(XPub);
78
79impl fmt::Debug for HDPublicKey {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        write!(f, "hdpub-{}", hex::encode(&self.0))
82    }
83}
84
85impl fmt::Display for HDPublicKey {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "hdpub-{}", hex::encode(&self.0))
88    }
89}
90
91impl cbored::Encode for HDPublicKey {
92    fn encode(&self, writer: &mut cbored::Writer) {
93        writer.encode(self.0.as_ref());
94    }
95}
96
97impl cbored::Decode for HDPublicKey {
98    fn decode<'a>(reader: &mut cbored::Reader<'a>) -> Result<Self, cbored::DecodeError> {
99        reader
100            .decode::<[u8; 64]>()
101            .map(|x| HDPublicKey(XPub::from_bytes(x)))
102    }
103}
104
105/// Standard Ed25519 Public Key (32 bytes)
106#[derive(Clone, CborRepr, PartialEq, Eq)]
107#[cborrepr(structure = "flat")]
108pub struct Ed25519PublicKey([u8; 32]);
109
110impl fmt::Debug for Ed25519PublicKey {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "ed25519pub-{}", hex::encode(&self.0))
113    }
114}
115
116impl fmt::Display for Ed25519PublicKey {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(f, "ed25519pub-{}", hex::encode(&self.0))
119    }
120}
121
122fn xprv_bip39_like_hashing(entropy: &[u8], password: &[u8]) -> XPrv {
123    const ITER: u32 = 4096;
124
125    let mut pbkdf2_result = [0; XPRV_SIZE];
126    let mut mac = Hmac::new(Sha512::new(), password);
127    pbkdf2(&mut mac, entropy.as_ref(), ITER, &mut pbkdf2_result);
128    XPrv::normalize_bytes_force3rd(pbkdf2_result)
129}
130
131/// BIP32 index (32 bit integer, where highest bit mark soft or hard derivation)
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub struct Bip32Index(u32);
134
135/// Enumeration for all cryptographic signature verification to prevent boolean blindness
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub enum SignatureVerification {
138    Passed,
139    Failed,
140}
141
142impl Bip32Index {
143    /// Get the raw u32 value
144    pub const fn u32(self) -> u32 {
145        self.0
146    }
147
148    /// Return whether the index is hard
149    pub const fn is_hard(self) -> bool {
150        (self.0 & 0x8000_0000) != 0
151    }
152
153    /// Return whether the index is soft
154    pub const fn is_soft(self) -> bool {
155        !self.is_hard()
156    }
157
158    /// Create a hard index from 31 bits
159    ///
160    /// if the 32th bit is set, it will raised a panic
161    pub const fn hard(v: u32) -> Self {
162        assert!((v & 0x8000_0000) == 0);
163        Bip32Index(v | 0x8000_0000)
164    }
165
166    /// Create a soft index from 31 bits
167    ///
168    /// if the 32th bit is set, it will raised a panic
169    pub const fn soft(v: u32) -> Self {
170        assert!((v & 0x8000_0000) == 0);
171        Bip32Index(v)
172    }
173}
174
175impl HDKey {
176    pub fn from_bip39_entropy(entropy: &[u8], password: &[u8]) -> Self {
177        Self(xprv_bip39_like_hashing(entropy, password))
178    }
179
180    pub fn bip32_derive(&self, index: Bip32Index) -> Self {
181        Self(self.0.derive(ed25519_bip32::DerivationScheme::V2, index.0))
182    }
183
184    pub fn bip32_derive_multiple(&self, mut indices: &[Bip32Index]) -> Self {
185        let mut sk = self.clone();
186        while !indices.is_empty() {
187            let index = indices[0];
188            sk = sk.bip32_derive(index);
189            indices = &indices[1..];
190        }
191        return sk;
192    }
193
194    pub fn strip_hd(&self) -> Ed25519ExtendedKey {
195        Ed25519ExtendedKey(self.0.extended_secret_key_bytes().clone())
196    }
197
198    pub fn to_public(&self) -> HDPublicKey {
199        HDPublicKey(self.0.public())
200    }
201
202    pub fn to_bech32_string(&self, hrp: &str) -> String {
203        bech32::encode(hrp, self.0.as_ref().to_base32(), Variant::Bech32).unwrap()
204    }
205
206    pub fn from_bytes(key: &[u8; 96]) -> Self {
207        HDKey(XPrv::from_bytes_verified(*key).unwrap())
208    }
209
210    pub fn to_bytes(&self) -> [u8; 96] {
211        let mut out = [0u8; 96];
212        out[0..64].copy_from_slice(self.0.extended_secret_key_bytes());
213        out[64..96].copy_from_slice(self.0.chain_code());
214        out
215    }
216}
217
218impl Ed25519ExtendedKey {
219    pub fn sign(&self, data: &[u8]) -> Ed25519Signature {
220        Ed25519Signature(ed25519::signature_extended(data, &self.0))
221    }
222
223    pub fn to_public(&self) -> Ed25519PublicKey {
224        Ed25519PublicKey(ed25519::extended_to_public(&self.0))
225    }
226
227    pub fn to_witness(&self, hash: &TxHash) -> VkeyWitness {
228        let data = hash.0;
229
230        let pk = self.to_public();
231        let sig = self.sign(&data);
232        VkeyWitness {
233            vkey: pk,
234            signature: sig,
235        }
236    }
237
238    pub fn from_bytes(key: &[u8; 64]) -> Self {
239        Self(key.clone())
240    }
241
242    pub fn to_bytes(&self) -> [u8; 64] {
243        self.0.clone()
244    }
245}
246
247impl Ed25519Key {
248    pub fn sign(&self, data: &[u8]) -> Ed25519Signature {
249        Ed25519Signature(ed25519::signature(data, &self.0))
250    }
251
252    pub fn to_public(&self) -> Ed25519PublicKey {
253        Ed25519PublicKey(ed25519::keypair_public(&self.0).clone())
254    }
255
256    pub fn from_bytes(secret_key: &[u8; 32]) -> Self {
257        let (kp, _) = ed25519::keypair(secret_key);
258        Self(kp)
259    }
260
261    pub fn to_witness(&self, hash: &TxHash) -> VkeyWitness {
262        let data = hash.0;
263
264        let pk = self.to_public();
265        let sig = self.sign(&data);
266        VkeyWitness {
267            vkey: pk,
268            signature: sig,
269        }
270    }
271
272    pub fn to_bytes(&self) -> [u8; 32] {
273        let mut out = [0u8; 32];
274        out.copy_from_slice(&self.0[0..32]);
275        out
276    }
277}
278
279impl HDPublicKey {
280    pub fn to_bytes(&self) -> [u8; 64] {
281        self.0.into()
282    }
283
284    pub fn from_bytes(pub_key: [u8; 64]) -> Self {
285        Self(XPub::from_bytes(pub_key))
286    }
287
288    pub fn strip_hd(&self) -> Ed25519PublicKey {
289        Ed25519PublicKey(self.0.public_key_bytes().clone())
290    }
291
292    pub fn hash(&self) -> Ed25519KeyHash {
293        let pk = self.0.public_key_bytes();
294        Ed25519KeyHash(blake2b_224(pk))
295    }
296
297    pub fn bip32_derive(&self, idx: Bip32Index) -> Self {
298        Self(
299            self.0
300                .derive(DerivationScheme::V2, idx.0)
301                .expect("valid soft derivation for public derivation"),
302        )
303    }
304}
305
306impl Ed25519PublicKey {
307    pub fn hash(&self) -> Ed25519KeyHash {
308        Ed25519KeyHash(blake2b_224(&self.0))
309    }
310
311    pub fn verify(&self, signature: &Ed25519Signature, data: &[u8]) -> SignatureVerification {
312        if ed25519::verify(data, &self.0, &signature.0) {
313            SignatureVerification::Passed
314        } else {
315            SignatureVerification::Failed
316        }
317    }
318
319    pub fn as_bytes(&self) -> &[u8; 32] {
320        &self.0
321    }
322
323    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
324        Self(*bytes)
325    }
326}
327
328impl Ed25519Signature {
329    pub fn as_bytes(&self) -> &[u8; 64] {
330        &self.0
331    }
332
333    pub fn from_bytes(bytes: &[u8; 64]) -> Self {
334        Self(*bytes)
335    }
336}
337
338#[cfg(test)]
339mod tests {
340    use super::*;
341
342    #[test]
343    fn sign_verify() {
344        let msg = &[1, 2, 3];
345        let key = Ed25519Key::from_bytes(&[1; 32]);
346        let pk = key.to_public();
347        let sig = key.sign(msg);
348        assert_eq!(pk.verify(&sig, msg), SignatureVerification::Passed);
349    }
350}