cardano_sdk/crypto/
key.rs1use 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#[derive(Clone)]
41pub struct HDKey(XPrv);
42
43#[derive(Clone)]
47pub struct Ed25519ExtendedKey([u8; 64]);
48
49#[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#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub struct Bip32Index(u32);
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub enum SignatureVerification {
138 Passed,
139 Failed,
140}
141
142impl Bip32Index {
143 pub const fn u32(self) -> u32 {
145 self.0
146 }
147
148 pub const fn is_hard(self) -> bool {
150 (self.0 & 0x8000_0000) != 0
151 }
152
153 pub const fn is_soft(self) -> bool {
155 !self.is_hard()
156 }
157
158 pub const fn hard(v: u32) -> Self {
162 assert!((v & 0x8000_0000) == 0);
163 Bip32Index(v | 0x8000_0000)
164 }
165
166 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}