Skip to content

Commit

Permalink
Merge branch 'rust-tweak'
Browse files Browse the repository at this point in the history
  • Loading branch information
benma committed Sep 20, 2024
2 parents d966071 + b01e86d commit 0f98e33
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 36 deletions.
10 changes: 0 additions & 10 deletions src/keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -1003,18 +1003,8 @@ bool keystore_secp256k1_schnorr_bip86_sign(
bool keystore_secp256k1_get_private_key(
const uint32_t* keypath,
const size_t keypath_len,
bool tweak_bip86,
uint8_t* key_out)
{
if (tweak_bip86) {
secp256k1_keypair __attribute__((__cleanup__(_cleanup_keypair))) keypair = {0};
secp256k1_xonly_pubkey pubkey = {0};
if (!_schnorr_bip86_keypair(keypath, keypath_len, &keypair, &pubkey)) {
return false;
}
const secp256k1_context* ctx = wally_get_secp_context();
return secp256k1_keypair_sec(ctx, key_out, &keypair) == 1;
}
struct ext_key xprv __attribute__((__cleanup__(keystore_zero_xkey))) = {0};
if (!_get_xprv_twice(keypath, keypath_len, &xprv)) {
return false;
Expand Down
2 changes: 0 additions & 2 deletions src/keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,11 @@ USE_RESULT bool keystore_secp256k1_schnorr_bip86_sign(
*
* @param[in] keypath derivation keypath
* @param[in] keypath_len number of elements in keypath
* @param[in] tweak_bip86 if true, the resulting private key is tweaked with the BIP-86 tweak.
* @param[out] key_out resulting private key, must be 32 bytes.
*/
USE_RESULT bool keystore_secp256k1_get_private_key(
const uint32_t* keypath,
size_t keypath_len,
bool tweak_bip86,
uint8_t* key_out);

#ifdef TESTING
Expand Down
22 changes: 16 additions & 6 deletions src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use pb::btc_sign_next_response::Type as NextType;
use sha2::{Digest, Sha256};

use bitcoin::hashes::Hash;
use bitcoin::key::TapTweak;

use streaming_silent_payments::SilentPayment;

Expand Down Expand Up @@ -720,13 +721,22 @@ async fn _process(request: &pb::BtcSignInitRequest) -> Result<Response, Error> {
}

if let Some(ref mut silent_payment) = silent_payment {
let private_key = bitcoin::secp256k1::SecretKey::from_slice(
&bitbox02::keystore::secp256k1_get_private_key(
&tx_input.keypath,
is_taproot(script_config_account),
)?,
let keypair = bitcoin::key::UntweakedKeypair::from_seckey_slice(
silent_payment.get_secp(),
&bitbox02::keystore::secp256k1_get_private_key(&tx_input.keypath)?,
)
.map_err(|_| Error::Generic)?;
.unwrap();
// For Taproot, only key path spends are allowed in silent payments, and we need to
// provide the key path spend private key, which means the internal key plus the tap
// tweak.
let private_key = if is_taproot(script_config_account) {
keypair
.tap_tweak(silent_payment.get_secp(), None)
.to_inner()
.secret_key()
} else {
keypair.secret_key()
};

silent_payment
.add_input(
Expand Down
21 changes: 3 additions & 18 deletions src/rust/bitbox02/src/keystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,12 @@ pub fn encode_xpub_at_keypath(keypath: &[u32]) -> Result<Vec<u8>, ()> {
}
}

pub fn secp256k1_get_private_key(
keypath: &[u32],
tweak_bip86: bool,
) -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
pub fn secp256k1_get_private_key(keypath: &[u32]) -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
let mut key = zeroize::Zeroizing::new(vec![0u8; 32]);
match unsafe {
bitbox02_sys::keystore_secp256k1_get_private_key(
keypath.as_ptr(),
keypath.len() as _,
tweak_bip86,
key.as_mut_ptr(),
)
} {
Expand Down Expand Up @@ -558,27 +554,16 @@ mod tests {
fn test_secp256k1_get_private_key() {
lock();
let keypath = &[84 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0];
assert!(secp256k1_get_private_key(keypath, false).is_err());
assert!(secp256k1_get_private_key(keypath).is_err());

mock_unlocked_using_mnemonic(
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
"",
);

assert_eq!(
hex::encode(secp256k1_get_private_key(keypath, false).unwrap()),
hex::encode(secp256k1_get_private_key(keypath).unwrap()),
"4604b4b710fe91f584fff084e1a9159fe4f8408fff380596a604948474ce4fa3"
);

// See first test vector in
// https://github.com/bitcoin/bips/blob/edffe529056f6dfd33d8f716fb871467c3c09263/bip-0086.mediawiki#test-vectors
// The below privte key's public key is: a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c.
assert_eq!(
hex::encode(
secp256k1_get_private_key(&[86 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0], true)
.unwrap()
),
"eaac016f36e8c18347fbacf05ab7966708fbfce7ce3bf1dc32a09dd0645db038",
);
}
}
4 changes: 4 additions & 0 deletions src/rust/streaming-silent-payments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ impl SilentPayment {
}
}

pub fn get_secp(&self) -> &Secp256k1<secp256k1::All> {
&self.secp
}

/// This must be called for *every* input of the transaction.
///
/// Important: if the input type cannot be represented by `InputType`, the transaction must be
Expand Down

0 comments on commit 0f98e33

Please sign in to comment.