diff --git a/src/descriptor/key_map.rs b/src/descriptor/key_map.rs index 3dd8c94ba..f4ff24867 100644 --- a/src/descriptor/key_map.rs +++ b/src/descriptor/key_map.rs @@ -128,11 +128,7 @@ impl GetKey for DescriptorSecretKey { Ok(None) } } - (Self::XPrv(descriptor_xkey), ref key_request @ KeyRequest::Bip32(ref key_source)) => { - if let Some(key) = descriptor_xkey.xkey.get_key(key_request.clone(), secp)? { - return Ok(Some(key)); - } - + (Self::XPrv(descriptor_xkey), KeyRequest::Bip32(ref key_source)) => { // A successful `matches()` already guarantees the requested key source's fingerprint equals our origin // (or, when there is no origin, the xkey's own) fingerprint. // @@ -479,4 +475,23 @@ mod tests { "SHOULD get NO private key when the requested path does not match the descriptor" ); } + + // Master xprv in the descriptor must not sign sibling paths (`/9/7` vs `/0/*`). + #[test] + fn get_key_bip32_rejects_sibling_with_master_xprv() { + let secp = Secp256k1::new(); + let master_xprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" + .parse::() + .unwrap(); + let fp = master_xprv.fingerprint(&secp); + let account_path: DerivationPath = "86h/1h/0h".parse().unwrap(); + let descriptor = format!("tr({master_xprv}/{account_path}/0/*)"); + let request_path: DerivationPath = format!("{account_path}/9/7").parse().unwrap(); + let key_request = KeyRequest::Bip32((fp, request_path)); + let (_, keymap) = Descriptor::parse_descriptor(&secp, &descriptor).unwrap(); + let result = keymap + .get_key(key_request, &secp) + .expect("key lookup should not fail"); + assert!(result.is_none(), "expected no matching key, got: {result:?}"); + } }