diff --git a/common/bolt12_merkle.c b/common/bolt12_merkle.c index 1bc5ad359..6ea63cb96 100644 --- a/common/bolt12_merkle.c +++ b/common/bolt12_merkle.c @@ -221,8 +221,6 @@ void sighash_from_merkle(const char *messagename, /* We use the SHA(pubkey | publictweak); so reader cannot figure out the * tweak and derive the base key. - * - * Since key used to be x-only, we don't hash first byte! */ void payer_key_tweak(const struct pubkey *bolt12, const u8 *publictweak, size_t publictweaklen, @@ -234,7 +232,7 @@ void payer_key_tweak(const struct pubkey *bolt12, pubkey_to_der(rawkey, bolt12); sha256_init(&sha); - sha256_update(&sha, rawkey + 1, sizeof(rawkey) - 1); + sha256_update(&sha, rawkey, sizeof(rawkey)); sha256_update(&sha, memcheck(publictweak, publictweaklen), publictweaklen); diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index b9d3f54b5..38a9b25f2 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -28,7 +28,7 @@ struct secret *dev_force_bip32_seed; struct { struct secret hsm_secret; struct ext_key bip32; - secp256k1_keypair bolt12; + struct secret bolt12; struct secret derived_secret; } secretstuff; @@ -636,26 +636,29 @@ static u8 *handle_sign_bolt12(struct hsmd_client *c, const u8 *msg_in) node_schnorrkey(&kp, NULL); } else { /* If we're tweaking key, we use bolt12 key */ + struct privkey tweakedkey; struct pubkey bolt12; struct sha256 tweak; - if (secp256k1_keypair_pub(secp256k1_ctx, - &bolt12.pubkey, - &secretstuff.bolt12) != 1) - hsmd_status_failed( - STATUS_FAIL_INTERNAL_ERROR, - "Could not derive bolt12 public key."); + if (secp256k1_ec_pubkey_create(secp256k1_ctx, &bolt12.pubkey, + secretstuff.bolt12.data) != 1) + hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could derive bolt12 public key."); + payer_key_tweak(&bolt12, publictweak, tal_bytelen(publictweak), &tweak); - kp = secretstuff.bolt12; + tweakedkey.secret = secretstuff.bolt12; + if (secp256k1_ec_seckey_tweak_add(secp256k1_ctx, + tweakedkey.secret.data, + tweak.u.u8) != 1) + hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could tweak bolt12 key."); - if (secp256k1_keypair_xonly_tweak_add(secp256k1_ctx, - &kp, - tweak.u.u8) != 1) { - return hsmd_status_bad_request_fmt( - c, msg_in, "Failed to get tweak key"); - } + if (secp256k1_keypair_create(secp256k1_ctx, &kp, + tweakedkey.secret.data) != 1) + hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Failed to derive bolt12 keypair"); } if (!secp256k1_schnorrsig_sign32(secp256k1_ctx, sig.u8, @@ -1759,10 +1762,8 @@ u8 *hsmd_init(struct secret hsm_secret, /* libwally says: The private key with prefix byte 0; remove it * for libsecp256k1. */ - if (secp256k1_keypair_create(secp256k1_ctx, &secretstuff.bolt12, - child_extkey.priv_key+1) != 1) - hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't derive bolt12 keypair"); + memcpy(&secretstuff.bolt12, child_extkey.priv_key+1, + sizeof(secretstuff.bolt12)); /* Now we can consider ourselves initialized, and we won't get * upset if we get a non-init message. */ @@ -1773,19 +1774,11 @@ u8 *hsmd_init(struct secret hsm_secret, node_id_from_pubkey(&node_id, &key); /* We also give it the base key for bolt12 payerids */ - if (secp256k1_keypair_pub(secp256k1_ctx, &bolt12.pubkey, - &secretstuff.bolt12) != 1) + if (secp256k1_ec_pubkey_create(secp256k1_ctx, &bolt12.pubkey, + secretstuff.bolt12.data) != 1) hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could derive bolt12 public key."); - /* For compatibility, we have to invert y-odd keys */ - u8 raw[PUBKEY_CMPR_LEN]; - pubkey_to_der(raw, &bolt12); - if (raw[0] == SECP256K1_TAG_PUBKEY_ODD) { - raw[0] = SECP256K1_TAG_PUBKEY_EVEN; - pubkey_from_der(raw, sizeof(raw), &bolt12); - } - /*~ We derive a secret for onion_message's self_id so we can tell * if it used a path we created (i.e. do not leak our public id!) */ hkdf_sha256(&onion_reply_secret, sizeof(onion_reply_secret), diff --git a/tests/test_pay.py b/tests/test_pay.py index 49c778507..ac1886190 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -5329,13 +5329,13 @@ def test_payerkey(node_factory): """payerkey calculation should not change across releases!""" nodes = node_factory.get_nodes(7) - expected_keys = ["ed648d8c53c73eb4ef97f3e9586ecfd86e2628037dd91e96ecdc469467dcc1b2", - "ee90e2adcf0e12c5dd1d802af792a4f4b18fd3926a9cc325ffe181bab1c48661", - "17b9ecb1870b5d3896e88247fcb592833fbee8abb5e89673d16560b0ed38f5c6", - "d37f723b611c15b7af394984aea84837d85371ba9eee95364b3c9f89a086f7bf", - "b33482c9753af9deb6df365cf834eccaab7afb24d080caaf87a57010f78f5817", - "f1d699068e3d276eddf9fc4caa0955604a34ee9b9b6529a1ec2eacebb82eb11e", - "4ef73851fe22604e9b7034f548bcb79583ec503983879c56963b9a40fc854758"] + expected_keys = ["294ec1cd3f100947fe859d71a42cb87932e36e7771abf2d50b02a7a92be8e4d5", + "6a4a3b6b0c694da6f14629ca5140713fc703591a6d8aae5c79ba9b5556fc5723", + "defd2b1f3004b0145351f469f34512c6fa4d02fe891a977bafdb34fe7b73ea48", + "eccb00c0a3c760465bb69a6297d7cfa5bcbd989d5a88e435bd8d6e4c723013cd", + "1b4bfa652f0df7498d734b0ca888b4e3b07f59e1a974ec7d4a9d6046e8e5ab92", + "fc91d60b061e517f9182e3e40ea14c27df520c51db204f1409ff50e5cf9a5e4d", + "a3bbda0137722ba62207b9d3e5e6cc2a11e58480f801892093e01383aacb7fb2"] for n, k in zip(nodes, expected_keys): b12 = n.rpc.createinvoicerequest('lnr1qvsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrcyyrjjthf4rh99n7equvlrzrlalcacxj4y9hgzxc79yrntrth6mp3nkvssy5mac4pkfq2m3gq4ttajwh097s')['bolt12']