diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index c71b92ce6..38b8c0b81 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -43,7 +43,7 @@ typedef struct { /** Opaque data structure that holds a signer's _secret_ nonce. * - * Guaranteed to be 68 bytes in size. + * Guaranteed to be 132 bytes in size. * * WARNING: This structure MUST NOT be copied or read or written to directly. A * signer who is online throughout the whole process and can keep this @@ -57,7 +57,7 @@ typedef struct { * leak the secret signing key. */ typedef struct { - unsigned char data[68]; + unsigned char data[132]; } secp256k1_musig_secnonce; /** Opaque data structure that holds a signer's public nonce. @@ -351,7 +351,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_twea * unless you really know what you are doing. * seckey: the 32-byte secret key that will later be used for signing, if * already known (can be NULL) - * pubkey: public key of the signer creating the nonce + * pubkey: public key of the signer creating the nonce. The secnonce + * output of this function cannot be used to sign for any + * other public key. * msg32: the 32-byte message that will later be signed, if already known * (can be NULL) * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate @@ -432,13 +434,20 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( * reuse. However, this is of course easily defeated if the secnonce has been * copied (or serialized). Remember that nonce reuse will leak the secret key! * + * For signing to succeed, the secnonce provided to this function must have + * been generated for the provided keypair. This means that when signing for a + * keypair consisting of a seckey and pubkey, the secnonce must have been + * created by calling musig_nonce_gen with that pubkey. Otherwise, the + * illegal_callback is called. + * * Returns: 0 if the arguments are invalid or the provided secnonce has already * been used for signing, 1 otherwise * Args: ctx: pointer to a context object * Out: partial_sig: pointer to struct to store the partial signature * In/Out: secnonce: pointer to the secnonce struct created in * musig_nonce_gen that has been never used in a - * partial_sign call before + * partial_sign call before and has been created for the + * keypair * In: keypair: pointer to keypair to sign the message with * keyagg_cache: pointer to the keyagg_cache that was output when the * aggregate public key for this session diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 91420731d..9a30cadb6 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -22,17 +22,19 @@ static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 }; -static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, secp256k1_scalar *k) { +static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, const secp256k1_scalar *k, secp256k1_ge *pk) { memcpy(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4); secp256k1_scalar_get_b32(&secnonce->data[4], &k[0]); secp256k1_scalar_get_b32(&secnonce->data[36], &k[1]); + secp256k1_point_save(&secnonce->data[68], pk); } -static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_musig_secnonce *secnonce) { +static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_ge *pk, secp256k1_musig_secnonce *secnonce) { int is_zero; ARG_CHECK(secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0); secp256k1_scalar_set_b32(&k[0], &secnonce->data[4], NULL); secp256k1_scalar_set_b32(&k[1], &secnonce->data[36], NULL); + secp256k1_point_load(pk, &secnonce->data[68]); /* We make very sure that the nonce isn't invalidated by checking the values * in addition to the magic. */ is_zero = secp256k1_scalar_is_zero(&k[0]) & secp256k1_scalar_is_zero(&k[1]); @@ -44,10 +46,12 @@ static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1 /* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) { secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag); - /* The flag argument is usually classified. So, above code makes the magic - * classified. However, we need the magic to be declassified to be able to - * compare it during secnonce_load. */ + /* The flag argument is usually classified. So, the line above makes the + * magic and public key classified. However, we need both to be + * declassified. Note that we don't declassify the entire object, because if + * flag is 0, then k[0] and k[1] have not been zeroed. */ secp256k1_declassify(ctx, secnonce->data, sizeof(secp256k1_musig_secnonce_magic)); + secp256k1_declassify(ctx, &secnonce->data[68], 64); } static const unsigned char secp256k1_musig_pubnonce_magic[4] = { 0xf5, 0x7a, 0x3d, 0xa0 }; @@ -355,6 +359,8 @@ int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secn size_t pk_ser_len = sizeof(pk_ser); unsigned char aggpk_ser[32]; unsigned char *aggpk_ser_ptr = NULL; + secp256k1_ge pk; + int pk_serialize_success; int ret = 1; VERIFY_CHECK(ctx != NULL); @@ -393,16 +399,19 @@ int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secn VERIFY_CHECK(ret_tmp); aggpk_ser_ptr = aggpk_ser; } - if (!secp256k1_ec_pubkey_serialize(ctx, pk_ser, &pk_ser_len, pubkey, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { return 0; } + pk_serialize_success = secp256k1_eckey_pubkey_serialize(&pk, pk_ser, &pk_ser_len, SECP256K1_EC_COMPRESSED); + /* A pubkey cannot be the point at infinity */ + VERIFY_CHECK(pk_serialize_success); VERIFY_CHECK(pk_ser_len == sizeof(pk_ser)); secp256k1_nonce_function_musig(k, session_id32, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); VERIFY_CHECK(!secp256k1_scalar_eq(&k[0], &k[1])); - secp256k1_musig_secnonce_save(secnonce, k); + secp256k1_musig_secnonce_save(secnonce, k, &pk); secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); for (i = 0; i < 2; i++) { @@ -562,7 +571,7 @@ static void secp256k1_musig_partial_sign_clear(secp256k1_scalar *sk, secp256k1_s int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_partial_sig *partial_sig, secp256k1_musig_secnonce *secnonce, const secp256k1_keypair *keypair, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { secp256k1_scalar sk; - secp256k1_ge pk; + secp256k1_ge pk, keypair_pk; secp256k1_scalar k[2]; secp256k1_scalar mu, s; secp256k1_keyagg_cache_internal cache_i; @@ -573,7 +582,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p ARG_CHECK(secnonce != NULL); /* Fails if the magic doesn't match */ - ret = secp256k1_musig_secnonce_load(ctx, k, secnonce); + ret = secp256k1_musig_secnonce_load(ctx, k, &pk, secnonce); /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls * of this function to fail */ memset(secnonce, 0, sizeof(*secnonce)); @@ -587,10 +596,12 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p ARG_CHECK(keyagg_cache != NULL); ARG_CHECK(session != NULL); - if (!secp256k1_keypair_load(ctx, &sk, &pk, keypair)) { + if (!secp256k1_keypair_load(ctx, &sk, &keypair_pk, keypair)) { secp256k1_musig_partial_sign_clear(&sk, k); return 0; } + ARG_CHECK(secp256k1_fe_equal_var(&pk.x, &keypair_pk.x) + && secp256k1_fe_equal_var(&pk.y, &keypair_pk.y)); if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { secp256k1_musig_partial_sign_clear(&sk, k); return 0; diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index ff6637d0a..9b7e7646a 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -126,7 +126,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { secp256k1_keypair keypair[2]; secp256k1_keypair invalid_keypair; unsigned char max64[64]; - unsigned char zeros68[68] = { 0 }; + unsigned char zeros132[132] = { 0 }; unsigned char session_id[2][32]; secp256k1_musig_secnonce secnonce[2]; secp256k1_musig_secnonce secnonce_tmp; @@ -228,19 +228,19 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, NULL, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, &keyagg_cache, NULL, 2) == 0); CHECK(ecount == 1); - CHECK(memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, &keyagg_cache, invalid_pk_ptr2, 2) == 0); CHECK(ecount == 2); - CHECK(memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, &keyagg_cache, invalid_pk_ptr3, 3) == 0); CHECK(ecount == 3); - CHECK(memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, &keyagg_cache, pk_ptr, 0) == 0); CHECK(ecount == 4); - CHECK(memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK(secp256k1_musig_pubkey_agg(vrfy, scratch, &agg_pk, &keyagg_cache, NULL, 0) == 0); CHECK(ecount == 5); - CHECK(memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK(secp256k1_musig_pubkey_agg(none, scratch, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_agg(sign, scratch, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); @@ -253,7 +253,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 1); CHECK(secp256k1_musig_pubkey_get(none, &full_agg_pk, NULL) == 0); CHECK(ecount == 2); - CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros68, sizeof(full_agg_pk)) == 0); + CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros132, sizeof(full_agg_pk)) == 0); /** Tweaking **/ { @@ -277,20 +277,20 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { tmp_keyagg_cache = keyagg_cache; CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, NULL, tweak) == 0); CHECK(ecount == 1); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); tmp_keyagg_cache = keyagg_cache; CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &tmp_keyagg_cache, NULL) == 0); CHECK(ecount == 2); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); tmp_keyagg_cache = keyagg_cache; CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0); CHECK(ecount == 2); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); tmp_keyagg_cache = keyagg_cache; /* Uninitialized keyagg_cache */ CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &invalid_keyagg_cache, tweak) == 0); CHECK(ecount == 3); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); } } @@ -308,18 +308,18 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 3); CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], NULL, sk[0], &pk[0], msg, &keyagg_cache, max64) == 0); CHECK(ecount == 4); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); /* no seckey and session_id is 0 */ - CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], zeros68, NULL, &pk[0], msg, &keyagg_cache, max64) == 0); + CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], zeros132, NULL, &pk[0], msg, &keyagg_cache, max64) == 0); CHECK(ecount == 4); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); /* session_id 0 is fine when a seckey is provided */ - CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], zeros68, sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); + CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], zeros132, sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], session_id[0], NULL, &pk[0], msg, &keyagg_cache, max64) == 1); CHECK(ecount == 4); /* invalid seckey */ CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], session_id[0], max64, &pk[0], msg, &keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); CHECK(ecount == 4); CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], session_id[0], sk[0], NULL, msg, &keyagg_cache, max64) == 0); CHECK(ecount == 5); @@ -331,7 +331,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 6); CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &invalid_keyagg_cache, max64) == 0); CHECK(ecount == 7); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); CHECK(secp256k1_musig_nonce_gen(sign, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &keyagg_cache, NULL) == 1); CHECK(ecount == 7); @@ -345,10 +345,10 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 1); CHECK(secp256k1_musig_pubnonce_serialize(none, pubnonce_ser, NULL) == 0); CHECK(ecount == 2); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros68, sizeof(pubnonce_ser)) == 0); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); CHECK(secp256k1_musig_pubnonce_serialize(none, pubnonce_ser, &invalid_pubnonce) == 0); CHECK(ecount == 3); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros68, sizeof(pubnonce_ser)) == 0); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); CHECK(secp256k1_musig_pubnonce_serialize(none, pubnonce_ser, &pubnonce[0]) == 1); ecount = 0; @@ -357,7 +357,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 1); CHECK(secp256k1_musig_pubnonce_parse(none, &pubnonce[0], NULL) == 0); CHECK(ecount == 2); - CHECK(secp256k1_musig_pubnonce_parse(none, &pubnonce[0], zeros68) == 0); + CHECK(secp256k1_musig_pubnonce_parse(none, &pubnonce[0], zeros132) == 0); CHECK(ecount == 2); CHECK(secp256k1_musig_pubnonce_parse(none, &pubnonce[0], pubnonce_ser) == 1); @@ -399,10 +399,10 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 1); CHECK(secp256k1_musig_aggnonce_serialize(none, aggnonce_ser, NULL) == 0); CHECK(ecount == 2); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros68, sizeof(aggnonce_ser)) == 0); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); CHECK(secp256k1_musig_aggnonce_serialize(none, aggnonce_ser, (secp256k1_musig_aggnonce*) &invalid_pubnonce) == 0); CHECK(ecount == 3); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros68, sizeof(aggnonce_ser)) == 0); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); CHECK(secp256k1_musig_aggnonce_serialize(none, aggnonce_ser, &aggnonce) == 1); ecount = 0; @@ -411,7 +411,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(ecount == 1); CHECK(secp256k1_musig_aggnonce_parse(none, &aggnonce, NULL) == 0); CHECK(ecount == 2); - CHECK(secp256k1_musig_aggnonce_parse(none, &aggnonce, zeros68) == 1); + CHECK(secp256k1_musig_aggnonce_parse(none, &aggnonce, zeros132) == 1); CHECK(secp256k1_musig_aggnonce_parse(none, &aggnonce, aggnonce_ser) == 1); { @@ -449,7 +449,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1); /* The secnonce is set to 0 and subsequent signing attempts fail */ - CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros68, sizeof(secnonce_tmp)) == 0); + CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros132, sizeof(secnonce_tmp)) == 0); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 0); CHECK(ecount == 1); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); @@ -466,17 +466,26 @@ void musig_api_tests(secp256k1_scratch_space *scratch) { CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &invalid_keypair, &keyagg_cache, &session) == 0); CHECK(ecount == 6); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + { + unsigned char sk_tmp[32]; + secp256k1_keypair keypair_tmp; + secp256k1_testrand256(sk_tmp); + CHECK(secp256k1_keypair_create(ctx, &keypair_tmp, sk_tmp)); + CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair_tmp, &keyagg_cache, &session) == 0); + CHECK(ecount == 7); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + } CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], NULL, &session) == 0); - CHECK(ecount == 7); + CHECK(ecount == 8); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], &invalid_keyagg_cache, &session) == 0); - CHECK(ecount == 8); + CHECK(ecount == 9); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, NULL) == 0); - CHECK(ecount == 9); + CHECK(ecount == 10); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &invalid_session) == 0); - CHECK(ecount == 10); + CHECK(ecount == 11); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(none, &partial_sig[0], &secnonce[0], &keypair[0], &keyagg_cache, &session) == 1); @@ -742,7 +751,7 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) { CHECK(secp256k1_musig_pubkey_agg(ctx, scratch, &agg_pk_b, &keyagg_cache_b, pk_b_ptr, 2) == 1); CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce_a[0], &pubnonce_a[0], seed_a[0], sk_a[0], &pk_a[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce_a[1], &pubnonce_a[1], seed_a[1], sk_a[1], &pk_b[1], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce_a[1], &pubnonce_a[1], seed_a[1], sk_a[1], &pk_a[1], NULL, NULL, NULL) == 1); CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce_b[0], &pubnonce_b[0], seed_b[0], sk_b[0], &pk_b[0], NULL, NULL, NULL) == 1); CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce_b[1], &pubnonce_b[1], seed_b[1], sk_b[1], &pk_b[1], NULL, NULL, NULL) == 1); @@ -1045,7 +1054,8 @@ void musig_test_vectors_noncegen(void) { CHECK(secp256k1_ec_pubkey_parse(ctx, &pk, c->pk, sizeof(c->pk))); CHECK(secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, c->rand_, sk, &pk, msg, keyagg_cache_ptr, extra_in) == 1); - CHECK(secp256k1_memcmp_var(&secnonce.data[4], c->expected, sizeof(secnonce)-4) == 0); + CHECK(secp256k1_memcmp_var(&secnonce.data[4], c->expected, 2*32) == 0); + CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); } } @@ -1080,6 +1090,16 @@ void musig_test_vectors_nonceagg(void) { } } +void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) { + secp256k1_ge pk; + secp256k1_scalar k[2]; + + secp256k1_scalar_set_b32(&k[0], &secnonce64[0], NULL); + secp256k1_scalar_set_b32(&k[1], &secnonce64[32], NULL); + CHECK(secp256k1_pubkey_load(ctx, &pk, pubkey)); + secp256k1_musig_secnonce_save(secnonce, k, &pk); +} + void musig_test_vectors_signverify(void) { size_t i; const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; @@ -1103,20 +1123,20 @@ void musig_test_vectors_signverify(void) { CHECK(secp256k1_musig_aggnonce_parse(ctx, &aggnonce, vector->aggnonces[c->aggnonce_index])); CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); - memcpy(&secnonce.data[0], secp256k1_musig_secnonce_magic, 4); - memcpy(&secnonce.data[4], vector->secnonces[0], sizeof(secnonce.data) - 4); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); CHECK(secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); CHECK(secp256k1_musig_partial_sig_serialize(ctx, partial_sig32, &partial_sig)); CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); CHECK(secp256k1_musig_pubnonce_parse(ctx, &pubnonce, vector->pubnonces[0])); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); CHECK(secp256k1_musig_partial_sig_verify(ctx, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); } for (i = 0; i < sizeof(vector->sign_error_case)/sizeof(vector->sign_error_case[0]); i++) { const struct musig_sign_error_case *c = &vector->sign_error_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_pubkey pubkey; secp256k1_musig_aggnonce aggnonce; secp256k1_musig_session session; secp256k1_musig_partial_sig partial_sig; @@ -1143,8 +1163,8 @@ void musig_test_vectors_signverify(void) { } CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); - memcpy(&secnonce.data[0], secp256k1_musig_secnonce_magic, 4); - memcpy(&secnonce.data[4], vector->secnonces[c->secnonce_index], sizeof(secnonce.data) - 4); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); { /* In the last test vector we sign with an invalid secnonce, which * triggers an illegal_callback. Hence, we need to use a custom @@ -1231,8 +1251,7 @@ void musig_test_vectors_tweak(void) { secp256k1_keypair keypair; unsigned char partial_sig32[32]; - memcpy(&secnonce.data[0], secp256k1_musig_secnonce_magic, 4); - memcpy(&secnonce.data[4], vector->secnonce, sizeof(secnonce.data) - 4); + musig_test_set_secnonce(&secnonce, vector->secnonce, &pubkey); CHECK(secp256k1_keypair_create(ctx, &keypair, vector->sk)); CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly));