1use k256::ecdsa;
2
3use coins_core::prelude::{Hash160, Hash160Digest, MarkedDigest, MarkedDigestOutput};
4
5use crate::{
6 path::{DerivationPath, KeyDerivation},
7 primitives::{Hint, KeyFingerprint, XKeyInfo},
8 xkeys::{Parent, XPriv, XPub, SEED},
9 Bip32Error,
10};
11
12pub trait DerivedKey {
15 fn derivation(&self) -> &KeyDerivation;
17
18 fn same_root<K: DerivedKey>(&self, other: &K) -> bool {
21 self.derivation().same_root(other.derivation())
22 }
23
24 fn is_possible_ancestor_of<K: DerivedKey>(&self, other: &K) -> bool {
32 self.derivation()
33 .is_possible_ancestor_of(other.derivation())
34 }
35
36 fn path_to_descendant<K: DerivedKey>(&self, other: &K) -> Option<DerivationPath> {
41 self.derivation().path_to_descendant(other.derivation())
42 }
43}
44
45#[derive(Debug, Clone)]
47#[cfg_attr(
48 any(feature = "mainnet", feature = "testnet"),
49 derive(serde::Serialize, serde::Deserialize)
50)]
51pub struct DerivedXPriv {
52 xpriv: XPriv,
53 derivation: KeyDerivation,
54}
55
56inherit_signer!(DerivedXPriv.xpriv);
57
58impl AsRef<XPriv> for DerivedXPriv {
59 fn as_ref(&self) -> &XPriv {
60 &self.xpriv
61 }
62}
63
64impl AsRef<XKeyInfo> for DerivedXPriv {
65 fn as_ref(&self) -> &XKeyInfo {
66 &self.xpriv.xkey_info
67 }
68}
69
70impl AsRef<ecdsa::SigningKey> for DerivedXPriv {
71 fn as_ref(&self) -> &ecdsa::SigningKey {
72 &self.xpriv.key
73 }
74}
75
76impl DerivedKey for DerivedXPriv {
77 fn derivation(&self) -> &KeyDerivation {
78 &self.derivation
79 }
80}
81
82impl DerivedXPriv {
83 pub const fn new(xpriv: XPriv, derivation: KeyDerivation) -> Self {
86 Self { xpriv, derivation }
87 }
88
89 pub fn is_private_ancestor_of(&self, other: &DerivedXPub) -> Result<bool, Bip32Error> {
92 if let Some(path) = self.path_to_descendant(other) {
93 let descendant = self.derive_path(path)?;
94 dbg!(descendant.verify_key());
95 dbg!(&other);
96 Ok(descendant.verify_key() == *other)
97 } else {
98 Ok(false)
99 }
100 }
101
102 pub fn root_node(
104 hmac_key: &[u8],
105 data: &[u8],
106 hint: Option<Hint>,
107 ) -> Result<DerivedXPriv, Bip32Error> {
108 Self::custom_root_node(hmac_key, data, hint)
109 }
110
111 pub fn root_from_seed(data: &[u8], hint: Option<Hint>) -> Result<DerivedXPriv, Bip32Error> {
118 Self::custom_root_from_seed(data, hint)
119 }
120
121 pub fn custom_root_node(
123 hmac_key: &[u8],
124 data: &[u8],
125 hint: Option<Hint>,
126 ) -> Result<DerivedXPriv, Bip32Error> {
127 let xpriv = XPriv::custom_root_node(hmac_key, data, hint)?;
128
129 let derivation = KeyDerivation {
130 root: xpriv.fingerprint(),
131 path: vec![].into(),
132 };
133
134 Ok(DerivedXPriv { xpriv, derivation })
135 }
136
137 pub fn custom_root_from_seed(
144 data: &[u8],
145 hint: Option<Hint>,
146 ) -> Result<DerivedXPriv, Bip32Error> {
147 Self::custom_root_node(SEED, data, hint)
148 }
149
150 pub fn verify_key(&self) -> DerivedXPub {
152 DerivedXPub {
153 xpub: self.xpriv.verify_key(),
154 derivation: self.derivation.clone(),
155 }
156 }
157}
158
159impl Parent for DerivedXPriv {
160 fn derive_child(&self, index: u32) -> Result<Self, Bip32Error> {
161 Ok(Self {
162 xpriv: self.xpriv.derive_child(index)?,
163 derivation: self.derivation.extended(index),
164 })
165 }
166}
167
168#[derive(Debug, Clone, PartialEq)]
170#[cfg_attr(
171 any(feature = "mainnet", feature = "testnet"),
172 derive(serde::Serialize, serde::Deserialize)
173)]
174pub struct DerivedXPub {
175 xpub: XPub,
176 derivation: KeyDerivation,
177}
178
179inherit_verifier!(DerivedXPub.xpub);
180
181impl AsRef<XPub> for DerivedXPub {
182 fn as_ref(&self) -> &XPub {
183 &self.xpub
184 }
185}
186
187impl AsRef<XKeyInfo> for DerivedXPub {
188 fn as_ref(&self) -> &XKeyInfo {
189 &self.xpub.xkey_info
190 }
191}
192
193impl AsRef<ecdsa::VerifyingKey> for DerivedXPub {
194 fn as_ref(&self) -> &ecdsa::VerifyingKey {
195 &self.xpub.key
196 }
197}
198
199impl Parent for DerivedXPub {
200 fn derive_child(&self, index: u32) -> Result<Self, Bip32Error> {
201 Ok(Self {
202 xpub: self.xpub.derive_child(index)?,
203 derivation: self.derivation.extended(index),
204 })
205 }
206}
207
208impl DerivedKey for DerivedXPub {
209 fn derivation(&self) -> &KeyDerivation {
210 &self.derivation
211 }
212}
213
214impl DerivedXPub {
215 pub const fn new(xpub: XPub, derivation: KeyDerivation) -> Self {
218 Self { xpub, derivation }
219 }
220
221 pub fn is_public_ancestor_of(&self, other: &DerivedXPub) -> Result<bool, Bip32Error> {
223 if let Some(path) = self.path_to_descendant(other) {
224 let descendant = self.derive_path(path)?;
225 Ok(descendant == *other)
226 } else {
227 Ok(false)
228 }
229 }
230}
231
232pub struct DerivedPubkey {
234 key: ecdsa::VerifyingKey,
235 derivation: KeyDerivation,
236}
237
238impl std::fmt::Debug for DerivedPubkey {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240 f.debug_struct("DerivedPubkey")
241 .field("public key", &self.key.to_sec1_bytes())
242 .field("key fingerprint", &self.fingerprint())
243 .field("derivation", &self.derivation)
244 .finish()
245 }
246}
247
248inherit_verifier!(DerivedPubkey.key);
249
250impl DerivedKey for DerivedPubkey {
251 fn derivation(&self) -> &KeyDerivation {
252 &self.derivation
253 }
254}
255
256impl AsRef<ecdsa::VerifyingKey> for DerivedPubkey {
257 fn as_ref(&self) -> &ecdsa::VerifyingKey {
258 &self.key
259 }
260}
261
262impl DerivedPubkey {
263 pub const fn new(key: ecdsa::VerifyingKey, derivation: KeyDerivation) -> Self {
265 Self { key, derivation }
266 }
267
268 pub fn pubkey_hash160(&self) -> Hash160Digest {
270 Hash160::digest_marked(self.key.to_sec1_bytes().as_ref())
271 }
272
273 pub fn fingerprint(&self) -> KeyFingerprint {
276 let digest = self.pubkey_hash160();
277 let mut buf = [0u8; 4];
278 buf.copy_from_slice(&digest.as_slice()[..4]);
279 buf.into()
280 }
281}
282
283#[cfg(test)]
284mod test {
285 use super::*;
286 use crate::{
287 enc::{MainnetEncoder, XKeyEncoder},
288 path::DerivationPath,
289 prelude::*,
290 primitives::*,
291 BIP32_HARDEN,
292 };
293 use coins_core::hashes::*;
294 use k256::ecdsa::signature::{DigestSigner, DigestVerifier};
295
296 use hex;
297
298 struct KeyDeriv<'a> {
299 pub(crate) path: &'a [u32],
300 }
301
302 fn validate_descendant(d: &KeyDeriv, m: &DerivedXPriv) {
303 let path: DerivationPath = d.path.into();
304
305 let m_pub = m.verify_key();
306
307 let xpriv = m.derive_path(&path).unwrap();
308 let xpub = xpriv.verify_key();
309 assert!(m.same_root(&xpriv));
310 assert!(m.same_root(&xpub));
311 assert!(m.is_possible_ancestor_of(&xpriv));
312 assert!(m.is_possible_ancestor_of(&xpub));
313
314 let result = m.is_private_ancestor_of(&xpub).expect("should work");
315
316 if !result {
317 panic!("failed validate_descendant is_private_ancestor_of");
318 }
319
320 let result = m_pub.is_public_ancestor_of(&xpub);
321
322 match result {
323 Ok(true) => {}
324 Ok(false) => panic!("failed validate_descendant is_public_ancestor_of"),
325 Err(_) => {
326 let path: DerivationPath = d.path.into();
327 assert!(
328 path.last_hardened().1.is_some(),
329 "is_public_ancestor_of failed for unhardened path"
330 )
331 }
332 }
333
334 let derived_path = m
335 .path_to_descendant(&xpriv)
336 .expect("expected a path to descendant");
337 assert_eq!(&path, &derived_path, "derived path is not as expected");
338 }
339
340 #[test]
341 fn bip32_vector_1() {
342 let seed: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
343
344 let xpriv = DerivedXPriv::root_from_seed(&seed, Some(Hint::Legacy)).unwrap();
345
346 let descendants = [
347 KeyDeriv {
348 path: &[BIP32_HARDEN],
349 },
350 KeyDeriv {
351 path: &[BIP32_HARDEN, 1],
352 },
353 KeyDeriv {
354 path: &[BIP32_HARDEN, 1, 2 + BIP32_HARDEN],
355 },
356 KeyDeriv {
357 path: &[BIP32_HARDEN, 1, 2 + BIP32_HARDEN, 2],
358 },
359 KeyDeriv {
360 path: &[BIP32_HARDEN, 1, 2 + BIP32_HARDEN, 2, 1000000000],
361 },
362 ];
363
364 for case in descendants.iter() {
365 validate_descendant(case, &xpriv);
366 }
367 }
368
369 #[test]
370 fn bip32_vector_2() {
371 let seed = hex::decode("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542").unwrap();
372
373 let xpriv = DerivedXPriv::root_from_seed(&seed, Some(Hint::Legacy)).unwrap();
374
375 let descendants = [
376 KeyDeriv { path: &[0] },
377 KeyDeriv {
378 path: &[0, 2147483647 + BIP32_HARDEN],
379 },
380 KeyDeriv {
381 path: &[0, 2147483647 + BIP32_HARDEN, 1],
382 },
383 KeyDeriv {
384 path: &[0, 2147483647 + BIP32_HARDEN, 1, 2147483646 + BIP32_HARDEN],
385 },
386 KeyDeriv {
387 path: &[
388 0,
389 2147483647 + BIP32_HARDEN,
390 1,
391 2147483646 + BIP32_HARDEN,
392 2,
393 ],
394 },
395 ];
396
397 for case in descendants.iter() {
398 validate_descendant(case, &xpriv);
399 }
400 }
401
402 #[test]
403 fn bip32_vector_3() {
404 let seed = hex::decode("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be").unwrap();
405
406 let xpriv = DerivedXPriv::root_from_seed(&seed, Some(Hint::Legacy)).unwrap();
407
408 let descendants = [KeyDeriv {
409 path: &[BIP32_HARDEN],
410 }];
411
412 for case in descendants.iter() {
413 validate_descendant(case, &xpriv);
414 }
415 }
416
417 #[test]
418 fn it_can_sign_and_verify() {
419 let digest = Hash256::default();
420 let mut wrong_digest = Hash256::default();
421 wrong_digest.update([0u8]);
422
423 let xpriv_str = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi".to_owned();
424 let xpriv = MainnetEncoder::xpriv_from_base58(&xpriv_str).unwrap();
425 let fake_deriv = KeyDerivation {
426 root: [0, 0, 0, 0].into(),
427 path: (0..0).collect(),
428 };
429
430 let key = DerivedXPriv::new(xpriv, fake_deriv);
431 let key_pub = key.verify_key();
432
433 let sig: Signature = key.sign_digest(digest.clone());
435 key_pub.verify_digest(digest.clone(), &sig).unwrap();
436
437 let err_bad_sig = key_pub.verify_digest(wrong_digest.clone(), &sig);
438 match err_bad_sig {
439 Err(_) => {}
440 _ => panic!("expected signature validation error"),
441 }
442
443 let (sig, _): (Signature, RecoveryId) = key.sign_digest(digest.clone());
444 key_pub.verify_digest(digest, &sig).unwrap();
445
446 let err_bad_sig = key_pub.verify_digest(wrong_digest.clone(), &sig);
447 match err_bad_sig {
448 Err(_) => {}
449 _ => panic!("expected signature validation error"),
450 }
451 }
452
453 #[test]
454 fn it_can_descendant_sign_and_verify() {
455 let digest = Hash256::default();
456 let mut wrong_digest = Hash256::default();
457 wrong_digest.update([0u8]);
458
459 let path = vec![0u32, 1, 2];
460
461 let xpriv_str = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi".to_owned();
462 let xpriv = MainnetEncoder::xpriv_from_base58(&xpriv_str).unwrap();
463 let fake_deriv = KeyDerivation {
464 root: [0, 0, 0, 0].into(),
465 path: (0..0).collect(),
466 };
467
468 let key = DerivedXPriv::new(xpriv, fake_deriv.clone());
469 let key_pub = key.verify_key();
470 assert_eq!(key.derivation(), &fake_deriv);
471
472 let sig: Signature = key.derive_path(&path).unwrap().sign_digest(digest.clone());
474 key_pub
475 .derive_path(&path)
476 .unwrap()
477 .verify_digest(digest.clone(), &sig)
478 .unwrap();
479
480 let err_bad_sig = key_pub
481 .derive_path(&path)
482 .unwrap()
483 .verify_digest(wrong_digest.clone(), &sig);
484 match err_bad_sig {
485 Err(_) => {}
486 _ => panic!("expected signature validation error"),
487 }
488
489 let (sig, _): (Signature, RecoveryId) =
490 key.derive_path(&path).unwrap().sign_digest(digest.clone());
491 key_pub
492 .derive_path(&path)
493 .unwrap()
494 .verify_digest(digest.clone(), &sig)
495 .unwrap();
496
497 let err_bad_sig = key_pub
498 .derive_path(&path)
499 .unwrap()
500 .verify_digest(wrong_digest.clone(), &sig);
501 match err_bad_sig {
502 Err(_) => {}
503 _ => panic!("expected signature validation error"),
504 }
505
506 let sig: Signature = key.derive_path(&path).unwrap().sign_digest(digest.clone());
508 key_pub
509 .derive_path(&path)
510 .unwrap()
511 .verify_digest(digest.clone(), &sig)
512 .unwrap();
513
514 let err_bad_sig = key_pub
515 .derive_path(&path)
516 .unwrap()
517 .verify_digest(wrong_digest.clone(), &sig);
518 match err_bad_sig {
519 Err(_) => {}
520 _ => panic!("expected signature validation error"),
521 }
522
523 let (sig, recovery_id): (Signature, RecoveryId) =
525 key.derive_path(&path).unwrap().sign_digest(digest.clone());
526 key_pub
527 .derive_path(&path)
528 .unwrap()
529 .verify_digest(digest, &sig)
530 .unwrap();
531
532 let err_bad_sig = key_pub
533 .derive_path(&path)
534 .unwrap()
535 .verify_digest(wrong_digest.clone(), &sig);
536 match err_bad_sig {
537 Err(_) => {}
538 _ => panic!("expected signature validation error"),
539 }
540
541 let der_sig = hex::decode("304402200cc613393c11889ed1384388c9213b7778cfa0c7c2b6fcc080f0296fc8ac87d202205788d8994d61ce901d1ee22c5210994c235f17ddb3c31e0fc0ec9730ecf084ce").unwrap();
543 let rsv: [u8; 65] = [
544 12, 198, 19, 57, 60, 17, 136, 158, 209, 56, 67, 136, 201, 33, 59, 119, 120, 207, 160,
545 199, 194, 182, 252, 192, 128, 240, 41, 111, 200, 172, 135, 210, 87, 136, 216, 153, 77,
546 97, 206, 144, 29, 30, 226, 44, 82, 16, 153, 76, 35, 95, 23, 221, 179, 195, 30, 15, 192,
547 236, 151, 48, 236, 240, 132, 206, 1,
548 ];
549 assert_eq!(sig.to_der().as_bytes(), der_sig);
550 assert_eq!(&sig, &Signature::from_der(&der_sig).unwrap());
551 assert_eq!(sig.r().to_bytes().as_slice(), &rsv[..32]);
552 assert_eq!(sig.s().to_bytes().as_slice(), &rsv[32..64]);
553 assert_eq!(recovery_id.to_byte(), rsv[64]);
554 }
555
556 #[test]
557 fn it_instantiates_derived_xprivs_from_seeds() {
558 DerivedXPriv::custom_root_from_seed(&[0u8; 32][..], None).unwrap();
559
560 let err_too_short = DerivedXPriv::custom_root_from_seed(&[0u8; 2][..], None);
561 match err_too_short {
562 Err(Bip32Error::SeedTooShort) => {}
563 _ => panic!("expected err too short"),
564 }
565
566 let err_too_short = DerivedXPriv::custom_root_from_seed(&[0u8; 2][..], None);
567 match err_too_short {
568 Err(Bip32Error::SeedTooShort) => {}
569 _ => panic!("expected err too short"),
570 }
571 }
572
573 #[test]
574 fn it_checks_ancestry() {
575 let m = DerivedXPriv::custom_root_from_seed(&[0u8; 32][..], None).unwrap();
576 let m2 = DerivedXPriv::custom_root_from_seed(&[1u8; 32][..], None).unwrap();
577 let m_pub = m.verify_key();
578 let cases = [
579 (&m, &m_pub, true),
580 (&m2, &m_pub, false),
581 (&m, &m2.verify_key(), false),
582 (&m, &m.derive_child(33).unwrap().verify_key(), true),
583 (&m, &m_pub.derive_child(33).unwrap(), true),
584 (&m, &m2.derive_child(33).unwrap().verify_key(), false),
585 ];
586 for (i, case) in cases.iter().enumerate() {
587 dbg!(i);
588 assert_eq!(case.0.is_private_ancestor_of(case.1).unwrap(), case.2);
589 }
590 }
591}