Skip to content

Commit cbb837b

Browse files
committed
keystore: port secp256k1_schnorr_bip86_pubkey to Rust
Since the inclusion of the miniscript feature and rust-miniscript dep, we depend on rust-bitcoin and rust-secp256k1, so we can make use of it instead of manually wrapping secp256k1. This does not change the binary size. The deleted C test was already previously replicated in `test_schnorr_bip86_pubkey` in bip32.rs.
1 parent a05c0f2 commit cbb837b

File tree

6 files changed

+9
-135
lines changed

6 files changed

+9
-135
lines changed

src/keystore.c

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -826,46 +826,6 @@ USE_RESULT bool keystore_encode_xpub_at_keypath(
826826
WALLY_OK;
827827
}
828828

829-
static void _tagged_hash(const char* tag, const uint8_t* msg, size_t msg_len, uint8_t* hash_out)
830-
{
831-
uint8_t tag_hash[32] = {0};
832-
rust_sha256(tag, strlen(tag), tag_hash);
833-
void* hash_ctx = rust_sha256_new();
834-
rust_sha256_update(hash_ctx, tag_hash, sizeof(tag_hash));
835-
rust_sha256_update(hash_ctx, tag_hash, sizeof(tag_hash));
836-
rust_sha256_update(hash_ctx, msg, msg_len);
837-
rust_sha256_finish(&hash_ctx, hash_out);
838-
}
839-
840-
bool keystore_secp256k1_schnorr_bip86_pubkey(const uint8_t* pubkey33, uint8_t* pubkey_out)
841-
{
842-
const secp256k1_context* ctx = wally_get_secp_context();
843-
844-
secp256k1_pubkey pubkey = {0};
845-
if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkey33, 33)) {
846-
return false;
847-
}
848-
secp256k1_xonly_pubkey xonly_pubkey = {0};
849-
if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey, NULL, &pubkey)) {
850-
return false;
851-
}
852-
uint8_t xonly_pubkey_serialized[32] = {0};
853-
if (!secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_serialized, &xonly_pubkey)) {
854-
return false;
855-
}
856-
uint8_t hash[32] = {0};
857-
secp256k1_pubkey tweaked_pubkey = {0};
858-
_tagged_hash("TapTweak", xonly_pubkey_serialized, sizeof(xonly_pubkey_serialized), hash);
859-
if (!secp256k1_xonly_pubkey_tweak_add(ctx, &tweaked_pubkey, &xonly_pubkey, hash)) {
860-
return false;
861-
}
862-
secp256k1_xonly_pubkey tweaked_xonly_pubkey = {0};
863-
if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &tweaked_xonly_pubkey, NULL, &tweaked_pubkey)) {
864-
return false;
865-
}
866-
return secp256k1_xonly_pubkey_serialize(ctx, pubkey_out, &tweaked_xonly_pubkey) == 1;
867-
}
868-
869829
static bool _schnorr_keypair(
870830
const uint32_t* keypath,
871831
size_t keypath_len,

src/keystore.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -266,23 +266,7 @@ USE_RESULT bool keystore_encode_xpub_at_keypath(
266266
uint8_t* out);
267267

268268
/**
269-
* Return the tweaked taproot pubkey.
270-
*
271-
* Instead of returning the original pubkey directly, it is tweaked with the hash of the pubkey.
272-
*
273-
* See
274-
* https://github.com/bitcoin/bips/blob/edffe529056f6dfd33d8f716fb871467c3c09263/bip-0086.mediawiki#address-derivation
275-
*
276-
* @param[in] pubkey33 33 byte compressed pubkey.
277-
* @param[out] pubkey_out 32 byte x-only pubkey (see BIP-340 for details).
278-
*/
279-
USE_RESULT bool keystore_secp256k1_schnorr_bip86_pubkey(
280-
const uint8_t* pubkey33,
281-
uint8_t* pubkey_out);
282-
283-
/**
284-
* Sign a message that verifies against the pubkey returned by
285-
* `keystore_secp256k1_schnorr_bip86_pubkey()`.
269+
* Sign a message that verifies against the pubkey tweaked using BIP-86.
286270
*
287271
* @param[in] keypath derivation keypath
288272
* @param[in] keypath_len number of elements in keypath

src/rust/bitbox02-rust/src/bip32.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,14 @@ impl Xpub {
137137
/// See
138138
/// https://github.com/bitcoin/bips/blob/edffe529056f6dfd33d8f716fb871467c3c09263/bip-0086.mediawiki#address-derivation
139139
pub fn schnorr_bip86_pubkey(&self) -> Result<[u8; 32], ()> {
140-
bitbox02::keystore::secp256k1_schnorr_bip86_pubkey(self.public_key())
140+
use bitcoin::key::TapTweak;
141+
let untweaked_pubkey: bitcoin::key::UntweakedPublicKey =
142+
bitcoin::key::PublicKey::from_slice(self.public_key())
143+
.map_err(|_| ())?
144+
.into();
145+
let secp = bitcoin::secp256k1::Secp256k1::new();
146+
let (tweaked, _) = untweaked_pubkey.tap_tweak(&secp, None);
147+
Ok(tweaked.serialize())
141148
}
142149
}
143150

src/rust/bitbox02-sys/build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ const ALLOWLIST_FNS: &[&str] = &[
7474
"keystore_mock_unlocked",
7575
"keystore_secp256k1_get_private_key",
7676
"keystore_secp256k1_nonce_commit",
77-
"keystore_secp256k1_schnorr_bip86_pubkey",
7877
"keystore_secp256k1_schnorr_sign",
7978
"keystore_secp256k1_sign",
8079
"keystore_unlock",

src/rust/bitbox02/src/keystore.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,6 @@ pub fn secp256k1_schnorr_sign(
360360
}
361361
}
362362

363-
pub fn secp256k1_schnorr_bip86_pubkey(pubkey33: &[u8]) -> Result<[u8; 32], ()> {
364-
let mut pubkey = [0u8; 32];
365-
match unsafe {
366-
bitbox02_sys::keystore_secp256k1_schnorr_bip86_pubkey(
367-
pubkey33.as_ptr(),
368-
pubkey.as_mut_ptr(),
369-
)
370-
} {
371-
true => Ok(pubkey),
372-
false => Err(()),
373-
}
374-
}
375-
376363
#[cfg(test)]
377364
mod tests {
378365
use super::*;

test/unit-test/test_keystore.c

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -638,68 +638,6 @@ static void _test_secp256k1_schnorr_sign(void** state)
638638
}
639639
}
640640

641-
static void _test_keystore_secp256k1_schnorr_bip86_pubkey(void** state)
642-
{
643-
// Test vectors from:
644-
// https://github.com/bitcoin/bips/blob/edffe529056f6dfd33d8f716fb871467c3c09263/bip-0086.mediawiki#test-vectors
645-
// Here we only test the creation of the tweaked pubkkey.
646-
_mock_with_mnemonic(
647-
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon "
648-
"about",
649-
"");
650-
{
651-
const uint32_t keypath[] = {
652-
86 + BIP32_INITIAL_HARDENED_CHILD,
653-
0 + BIP32_INITIAL_HARDENED_CHILD,
654-
0 + BIP32_INITIAL_HARDENED_CHILD,
655-
0,
656-
0,
657-
};
658-
struct ext_key xpub = {0};
659-
assert_true(keystore_get_xpub(keypath, 5, &xpub));
660-
uint8_t pubkey[32] = {0};
661-
assert_true(keystore_secp256k1_schnorr_bip86_pubkey(xpub.pub_key, pubkey));
662-
const uint8_t expected_pubkey[32] =
663-
"\xa6\x08\x69\xf0\xdb\xcf\x1d\xc6\x59\xc9\xce\xcb\xaf\x80\x50\x13\x5e\xa9\xe8\xcd\xc4"
664-
"\x87\x05\x3f\x1d\xc6\x88\x09\x49\xdc\x68\x4c";
665-
assert_memory_equal(pubkey, expected_pubkey, sizeof(pubkey));
666-
}
667-
{
668-
const uint32_t keypath[] = {
669-
86 + BIP32_INITIAL_HARDENED_CHILD,
670-
0 + BIP32_INITIAL_HARDENED_CHILD,
671-
0 + BIP32_INITIAL_HARDENED_CHILD,
672-
0,
673-
1,
674-
};
675-
struct ext_key xpub = {0};
676-
assert_true(keystore_get_xpub(keypath, 5, &xpub));
677-
uint8_t pubkey[32] = {0};
678-
assert_true(keystore_secp256k1_schnorr_bip86_pubkey(xpub.pub_key, pubkey));
679-
const uint8_t expected_pubkey[32] =
680-
"\xa8\x2f\x29\x94\x4d\x65\xb8\x6a\xe6\xb5\xe5\xcc\x75\xe2\x94\xea\xd6\xc5\x93\x91\xa1"
681-
"\xed\xc5\xe0\x16\xe3\x49\x8c\x67\xfc\x7b\xbb";
682-
assert_memory_equal(pubkey, expected_pubkey, sizeof(pubkey));
683-
}
684-
{
685-
const uint32_t keypath[] = {
686-
86 + BIP32_INITIAL_HARDENED_CHILD,
687-
0 + BIP32_INITIAL_HARDENED_CHILD,
688-
0 + BIP32_INITIAL_HARDENED_CHILD,
689-
1,
690-
0,
691-
};
692-
struct ext_key xpub = {0};
693-
assert_true(keystore_get_xpub(keypath, 5, &xpub));
694-
uint8_t pubkey[32] = {0};
695-
assert_true(keystore_secp256k1_schnorr_bip86_pubkey(xpub.pub_key, pubkey));
696-
const uint8_t expected_pubkey[32] =
697-
"\x88\x2d\x74\xe5\xd0\x57\x2d\x5a\x81\x6c\xef\x00\x41\xa9\x6b\x6c\x1d\xe8\x32\xf6\xf9"
698-
"\x67\x6d\x96\x05\xc4\x4d\x5e\x9a\x97\xd3\xdc";
699-
assert_memory_equal(pubkey, expected_pubkey, sizeof(pubkey));
700-
}
701-
}
702-
703641
static void _test_keystore_secp256k1_schnorr_sign(void** state)
704642
{
705643
_mock_with_mnemonic(
@@ -762,7 +700,6 @@ int main(void)
762700
cmocka_unit_test(_test_keystore_create_and_store_seed),
763701
cmocka_unit_test(_test_keystore_get_ed25519_seed),
764702
cmocka_unit_test(_test_secp256k1_schnorr_sign),
765-
cmocka_unit_test(_test_keystore_secp256k1_schnorr_bip86_pubkey),
766703
cmocka_unit_test(_test_keystore_secp256k1_schnorr_sign),
767704
};
768705
return cmocka_run_group_tests(tests, NULL, NULL);

0 commit comments

Comments
 (0)