Merge pull request #73 from jonasnick/fix-musig-message

Require message in musig protocol in an earlier state
This commit is contained in:
Andrew Poelstra 2019-10-18 20:42:30 +00:00 committed by GitHub
commit cad7cc8f34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 102 deletions

View File

@ -151,9 +151,9 @@ SECP256K1_API int secp256k1_musig_pubkey_combine(
* NULL). If a non-unique session_id32 was given then a partial * NULL). If a non-unique session_id32 was given then a partial
* signature will LEAK THE SECRET KEY. * signature will LEAK THE SECRET KEY.
* msg32: the 32-byte message to be signed. Shouldn't be NULL unless you * msg32: the 32-byte message to be signed. Shouldn't be NULL unless you
* require sharing public nonces before the message is known * require sharing nonce commitments before the message is known
* because it reduces nonce misuse resistance. If NULL, must be * because it reduces nonce misuse resistance. If NULL, must be
* set with `musig_session_set_msg` before signing and verifying. * set with `musig_session_get_public_nonce`.
* combined_pk: the combined public key of all signers (cannot be NULL) * combined_pk: the combined public key of all signers (cannot be NULL)
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be * pk_hash32: the 32-byte hash of the signers' individual keys (cannot be
* NULL) * NULL)
@ -190,6 +190,8 @@ SECP256K1_API int secp256k1_musig_session_initialize(
* In: commitments: array of 32-byte nonce commitments (cannot be NULL) * In: commitments: array of 32-byte nonce commitments (cannot be NULL)
* n_commitments: the length of commitments and signers array. Must be the total * n_commitments: the length of commitments and signers array. Must be the total
* number of signers participating in the MuSig. * number of signers participating in the MuSig.
* msg32: the 32-byte message to be signed. Must be NULL if already
* set with `musig_session_initialize` otherwise can not be NULL.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_public_nonce( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_public_nonce(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -197,7 +199,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_publi
secp256k1_musig_session_signer_data *signers, secp256k1_musig_session_signer_data *signers,
secp256k1_pubkey *nonce, secp256k1_pubkey *nonce,
const unsigned char *const *commitments, const unsigned char *const *commitments,
size_t n_commitments size_t n_commitments,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Initializes a verifier session that can be used for verifying nonce commitments /** Initializes a verifier session that can be used for verifying nonce commitments
@ -209,9 +212,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_publi
* Out: session: the session structure to initialize (cannot be NULL) * Out: session: the session structure to initialize (cannot be NULL)
* signers: an array of signers' data to be initialized. Array length must * signers: an array of signers' data to be initialized. Array length must
* equal to `n_signers`(cannot be NULL) * equal to `n_signers`(cannot be NULL)
* In: msg32: the 32-byte message to be signed If NULL, must be set with * In: msg32: the 32-byte message to be signed (cannot be NULL)
* `musig_session_set_msg` before using the session for verifying
* partial signatures.
* combined_pk: the combined public key of all signers (cannot be NULL) * combined_pk: the combined public key of all signers (cannot be NULL)
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be NULL) * pk_hash32: the 32-byte hash of the signers' individual keys (cannot be NULL)
* commitments: array of 32-byte nonce commitments. Array length must equal to * commitments: array of 32-byte nonce commitments. Array length must equal to
@ -229,7 +230,7 @@ SECP256K1_API int secp256k1_musig_session_initialize_verifier(
const unsigned char *pk_hash32, const unsigned char *pk_hash32,
const unsigned char *const *commitments, const unsigned char *const *commitments,
size_t n_signers size_t n_signers
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7);
/** Checks a signer's public nonce against a commitment to said nonce, and update /** Checks a signer's public nonce against a commitment to said nonce, and update
* data structure if they match * data structure if they match
@ -275,20 +276,6 @@ SECP256K1_API int secp256k1_musig_session_combine_nonces(
const secp256k1_pubkey *adaptor const secp256k1_pubkey *adaptor
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Sets the message of a session if previously unset
*
* Returns 1 if the message was not set yet and is now successfully set
* 0 otherwise
* Args: ctx: pointer to a context object (cannot be NULL)
* session: the session structure to update with the message (cannot be NULL)
* In: msg32: the 32-byte message to be signed (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_set_msg(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a MuSig partial signature or adaptor signature /** Serialize a MuSig partial signature or adaptor signature
* *
* Returns: 1 when the signature could be serialized, 0 otherwise * Returns: 1 when the signature could be serialized, 0 otherwise

View File

@ -77,7 +77,7 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
/* Communication round 1: Exchange nonce commitments */ /* Communication round 1: Exchange nonce commitments */
for (i = 0; i < N_SIGNERS; i++) { for (i = 0; i < N_SIGNERS; i++) {
/* Set nonce commitments in the signer data and get the own public nonce */ /* Set nonce commitments in the signer data and get the own public nonce */
if (!secp256k1_musig_session_get_public_nonce(ctx, &musig_session[i], signer_data[i], &nonce[i], nonce_commitment_ptr, N_SIGNERS)) { if (!secp256k1_musig_session_get_public_nonce(ctx, &musig_session[i], signer_data[i], &nonce[i], nonce_commitment_ptr, N_SIGNERS, NULL)) {
return 0; return 0;
} }
} }

View File

@ -211,7 +211,7 @@ int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_m
return 1; return 1;
} }
int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, secp256k1_pubkey *nonce, const unsigned char *const *commitments, size_t n_commitments) { int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, secp256k1_pubkey *nonce, const unsigned char *const *commitments, size_t n_commitments, const unsigned char *msg32) {
secp256k1_sha256 sha; secp256k1_sha256 sha;
unsigned char nonce_commitments_hash[32]; unsigned char nonce_commitments_hash[32];
size_t i; size_t i;
@ -222,6 +222,10 @@ int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp2
ARG_CHECK(signers != NULL); ARG_CHECK(signers != NULL);
ARG_CHECK(nonce != NULL); ARG_CHECK(nonce != NULL);
ARG_CHECK(commitments != NULL); ARG_CHECK(commitments != NULL);
/* If the message was not set during initialization it must be set now. */
ARG_CHECK(!(!session->msg_is_set && msg32 == NULL));
/* The message can only be set once. */
ARG_CHECK(!(session->msg_is_set && msg32 != NULL));
if (!session->has_secret_data || n_commitments != session->n_signers) { if (!session->has_secret_data || n_commitments != session->n_signers) {
return 0; return 0;
@ -230,6 +234,10 @@ int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp2
ARG_CHECK(commitments[i] != NULL); ARG_CHECK(commitments[i] != NULL);
} }
if (msg32 != NULL) {
memcpy(session->msg, msg32, 32);
session->msg_is_set = 1;
}
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
for (i = 0; i < n_commitments; i++) { for (i = 0; i < n_commitments; i++) {
memcpy(signers[i].nonce_commitment, commitments[i], 32); memcpy(signers[i].nonce_commitment, commitments[i], 32);
@ -254,6 +262,7 @@ int secp256k1_musig_session_initialize_verifier(const secp256k1_context* ctx, se
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL); ARG_CHECK(session != NULL);
ARG_CHECK(signers != NULL); ARG_CHECK(signers != NULL);
ARG_CHECK(msg32 != NULL);
ARG_CHECK(combined_pk != NULL); ARG_CHECK(combined_pk != NULL);
ARG_CHECK(pk_hash32 != NULL); ARG_CHECK(pk_hash32 != NULL);
ARG_CHECK(commitments != NULL); ARG_CHECK(commitments != NULL);
@ -278,11 +287,8 @@ int secp256k1_musig_session_initialize_verifier(const secp256k1_context* ctx, se
memcpy(session->pk_hash, pk_hash32, 32); memcpy(session->pk_hash, pk_hash32, 32);
session->nonce_is_set = 0; session->nonce_is_set = 0;
session->msg_is_set = 0;
if (msg32 != NULL) {
memcpy(session->msg, msg32, 32);
session->msg_is_set = 1; session->msg_is_set = 1;
} memcpy(session->msg, msg32, 32);
session->has_secret_data = 0; session->has_secret_data = 0;
session->nonce_commitments_hash_is_set = 0; session->nonce_commitments_hash_is_set = 0;
@ -373,19 +379,6 @@ int secp256k1_musig_session_combine_nonces(const secp256k1_context* ctx, secp256
return 1; return 1;
} }
int secp256k1_musig_session_set_msg(const secp256k1_context* ctx, secp256k1_musig_session *session, const unsigned char *msg32) {
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(msg32 != NULL);
if (session->msg_is_set) {
return 0;
}
memcpy(session->msg, msg32, 32);
session->msg_is_set = 1;
return 1;
}
int secp256k1_musig_partial_signature_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_signature* sig) { int secp256k1_musig_partial_signature_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_signature* sig) {
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(out32 != NULL); ARG_CHECK(out32 != NULL);

View File

@ -91,6 +91,8 @@ signature process, which is also a supported mode) acts as follows.
length-32 byte arrays which can be communicated however is communicated. length-32 byte arrays which can be communicated however is communicated.
3. Once all signers nonce commitments have been received, the signer records 3. Once all signers nonce commitments have been received, the signer records
these commitments with the function `secp256k1_musig_session_get_public_nonce`. these commitments with the function `secp256k1_musig_session_get_public_nonce`.
If the signer did not provide a message to `secp256k1_musig_session_initialize`,
a message must be provided now.
This function updates in place This function updates in place
- the session state `session` - the session state `session`
- the array of signer data `signers` - the array of signer data `signers`
@ -111,9 +113,6 @@ signature process, which is also a supported mode) acts as follows.
- the array of signer data `signers` - the array of signer data `signers`
It outputs an auxiliary integer `nonce_is_negated` and has an auxiliary input It outputs an auxiliary integer `nonce_is_negated` and has an auxiliary input
`adaptor`. Both of these may be set to NULL for ordinary signing purposes. `adaptor`. Both of these may be set to NULL for ordinary signing purposes.
If the signer did not provide a message to `secp256k1_musig_session_initialize`,
a message must be provided now by calling `secp256k1_musig_session_set_msg` which
updates the session state in place.
6. The signer computes a partial signature `s_i` using the function 6. The signer computes a partial signature `s_i` using the function
`secp256k1_musig_partial_sign` which takes the session state as input and `secp256k1_musig_partial_sign` which takes the session state as input and
partial signature as output. partial signature as output.

View File

@ -136,13 +136,6 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_musig_session_initialize(sign, &session[0], signer0, nonce_commitment[0], session_id[0], msg, &combined_pk, pk_hash, 2, 0, ones) == 0); CHECK(secp256k1_musig_session_initialize(sign, &session[0], signer0, nonce_commitment[0], session_id[0], msg, &combined_pk, pk_hash, 2, 0, ones) == 0);
CHECK(ecount == 9); CHECK(ecount == 9);
{
secp256k1_musig_session session_without_msg;
CHECK(secp256k1_musig_session_initialize(sign, &session_without_msg, signer0, nonce_commitment[0], session_id[0], NULL, &combined_pk, pk_hash, 2, 0, sk[0]) == 1);
CHECK(secp256k1_musig_session_set_msg(none, &session_without_msg, msg) == 1);
CHECK(secp256k1_musig_session_set_msg(none, &session_without_msg, msg) == 0);
}
CHECK(secp256k1_musig_session_initialize(sign, &session[0], signer0, nonce_commitment[0], session_id[0], msg, &combined_pk, pk_hash, 2, 0, sk[0]) == 1); CHECK(secp256k1_musig_session_initialize(sign, &session[0], signer0, nonce_commitment[0], session_id[0], msg, &combined_pk, pk_hash, 2, 0, sk[0]) == 1);
CHECK(secp256k1_musig_session_initialize(sign, &session[1], signer1, nonce_commitment[1], session_id[1], msg, &combined_pk, pk_hash, 2, 1, sk[1]) == 1); CHECK(secp256k1_musig_session_initialize(sign, &session[1], signer1, nonce_commitment[1], session_id[1], msg, &combined_pk, pk_hash, 2, 1, sk[1]) == 1);
ncs[0] = nonce_commitment[0]; ncs[0] = nonce_commitment[0];
@ -153,20 +146,20 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
CHECK(ecount == 0); CHECK(ecount == 0);
CHECK(secp256k1_musig_session_initialize_verifier(none, NULL, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 2) == 0); CHECK(secp256k1_musig_session_initialize_verifier(none, NULL, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 2) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, NULL, &combined_pk, pk_hash, ncs, 2) == 1); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, NULL, &combined_pk, pk_hash, ncs, 2) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, NULL, pk_hash, ncs, 2) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, NULL, ncs, 2) == 0); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, NULL, pk_hash, ncs, 2) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, NULL, ncs, 2) == 0);
CHECK(ecount == 4);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, NULL, 2) == 0); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, NULL, 2) == 0);
CHECK(ecount == 4); CHECK(ecount == 5);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 0) == 0); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 0) == 0);
CHECK(ecount == 4); CHECK(ecount == 5);
if (SIZE_MAX > UINT32_MAX) { if (SIZE_MAX > UINT32_MAX) {
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, ((size_t) UINT32_MAX) + 2) == 0); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, ((size_t) UINT32_MAX) + 2) == 0);
} }
CHECK(ecount == 4); CHECK(ecount == 5);
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 2) == 1); CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, pk_hash, ncs, 2) == 1);
CHECK(secp256k1_musig_compute_messagehash(none, msghash, &verifier_session) == 0); CHECK(secp256k1_musig_compute_messagehash(none, msghash, &verifier_session) == 0);
@ -178,7 +171,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
secp256k1_pubkey nonce; secp256k1_pubkey nonce;
/* Can obtain public nonce after commitments have been exchanged; still can't sign */ /* Can obtain public nonce after commitments have been exchanged; still can't sign */
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &nonce, ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &nonce, ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_partial_sign(none, &session[0], &partial_sig[0]) == 0); CHECK(secp256k1_musig_partial_sign(none, &session[0], &partial_sig[0]) == 0);
CHECK(ecount == 0); CHECK(ecount == 0);
} }
@ -188,22 +181,22 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
{ {
secp256k1_pubkey public_nonce[3]; secp256k1_pubkey public_nonce[3];
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2, NULL) == 1);
CHECK(ecount == 0); CHECK(ecount == 0);
CHECK(secp256k1_musig_session_get_public_nonce(none, NULL, signer0, &public_nonce[0], ncs, 2) == 0); CHECK(secp256k1_musig_session_get_public_nonce(none, NULL, signer0, &public_nonce[0], ncs, 2, NULL) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], NULL, &public_nonce[0], ncs, 2) == 0); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], NULL, &public_nonce[0], ncs, 2, NULL) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, NULL, ncs, 2) == 0); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, NULL, ncs, 2, NULL) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], NULL, 2) == 0); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], NULL, 2, NULL) == 0);
CHECK(ecount == 4); CHECK(ecount == 4);
/* Number of commitments and number of signers are different */ /* Number of commitments and number of signers are different */
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 1) == 0); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 1, NULL) == 0);
CHECK(ecount == 4); CHECK(ecount == 4);
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[1], signer1, &public_nonce[1], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(none, &session[1], signer1, &public_nonce[1], ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_set_nonce(none, &signer0[0], &public_nonce[0]) == 1); CHECK(secp256k1_musig_set_nonce(none, &signer0[0], &public_nonce[0]) == 1);
CHECK(secp256k1_musig_set_nonce(none, &signer0[1], &public_nonce[0]) == 0); CHECK(secp256k1_musig_set_nonce(none, &signer0[1], &public_nonce[0]) == 0);
@ -404,14 +397,14 @@ int musig_state_machine_diff_signer_msghash_test(unsigned char *msghash, secp256
pks_tmp[0] = pks[0]; pks_tmp[0] = pks[0];
CHECK(secp256k1_ec_pubkey_create(ctx, &pks_tmp[1], sk_dummy) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pks_tmp[1], sk_dummy) == 1);
CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk_tmp, pk_hash_tmp, pks_tmp, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk_tmp, pk_hash_tmp, pks_tmp, 2) == 1);
CHECK(secp256k1_musig_session_initialize(ctx, &session_tmp, signers_tmp, nonce_commitment, session_id, msg, &combined_pk_tmp, pk_hash_tmp, 2, 0, sk_dummy) == 1); CHECK(secp256k1_musig_session_initialize(ctx, &session_tmp, signers_tmp, nonce_commitment, session_id, msg, &combined_pk_tmp, pk_hash_tmp, 2, 1, sk_dummy) == 1);
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 0, sk) == 1); CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 0, sk) == 1);
CHECK(memcmp(nonce_commitment, nonce_commitments[1], 32) == 0); CHECK(memcmp(nonce_commitment, nonce_commitments[1], 32) == 0);
/* Call get_public_nonce with different signers than the signers the session was /* Call get_public_nonce with different signers than the signers the session was
* initialized with. */ * initialized with. */
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session_tmp, signers, &nonce, nonce_commitments, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session_tmp, signers, &nonce, nonce_commitments, 2, NULL) == 1);
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers_tmp, &nonce, nonce_commitments, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers_tmp, &nonce, nonce_commitments, 2, NULL) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
CHECK(secp256k1_musig_session_combine_nonces(ctx, &session, signers, 2, NULL, NULL) == 1); CHECK(secp256k1_musig_session_combine_nonces(ctx, &session, signers, 2, NULL, NULL) == 1);
@ -438,7 +431,7 @@ int musig_state_machine_diff_signers_combine_nonce_test(secp256k1_pubkey *combin
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 1, sk) == 1); CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 1, sk) == 1);
ncs[0] = nonce_commitment_other; ncs[0] = nonce_commitment_other;
ncs[1] = nonce_commitment; ncs[1] = nonce_commitment;
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
@ -451,34 +444,44 @@ int musig_state_machine_diff_signers_combine_nonce_test(secp256k1_pubkey *combin
return secp256k1_musig_session_combine_nonces(ctx, &session, signers_to_use, 2, NULL, NULL); return secp256k1_musig_session_combine_nonces(ctx, &session, signers_to_use, 2, NULL, NULL);
} }
/* Recreates a session with the given session_id, signers, pk, msg etc. parameters /* Initializaes a session with the given session_id, signers, pk, msg etc.
* and tries to sign and verify the other signers partial signature. Both should fail * parameters but without a message. Will test that the message must be
* if msg is NULL. */ * provided with `get_public_nonce`.
int musig_state_machine_missing_msg_test(secp256k1_pubkey *pks, secp256k1_pubkey *combined_pk, unsigned char *pk_hash, unsigned char *nonce_commitment_other, secp256k1_pubkey *nonce_other, secp256k1_musig_partial_signature *partial_sig_other, unsigned char *sk, unsigned char *session_id, unsigned char *msg) { */
void musig_state_machine_late_msg_test(secp256k1_pubkey *pks, secp256k1_pubkey *combined_pk, unsigned char *pk_hash, unsigned char *nonce_commitment_other, secp256k1_pubkey *nonce_other, unsigned char *sk, unsigned char *session_id, unsigned char *msg) {
/* Create context for testing ARG_CHECKs by setting an illegal_callback. */
secp256k1_context *ctx_tmp = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
int ecount = 0;
secp256k1_musig_session session; secp256k1_musig_session session;
secp256k1_musig_session_signer_data signers[2]; secp256k1_musig_session_signer_data signers[2];
unsigned char nonce_commitment[32]; unsigned char nonce_commitment[32];
const unsigned char *ncs[2]; const unsigned char *ncs[2];
secp256k1_pubkey nonce; secp256k1_pubkey nonce;
secp256k1_musig_partial_signature partial_sig; secp256k1_musig_partial_signature partial_sig;
int partial_sign, partial_verify;
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 0, sk) == 1); secp256k1_context_set_illegal_callback(ctx_tmp, counting_illegal_callback_fn, &ecount);
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, NULL, combined_pk, pk_hash, 2, 1, sk) == 1);
ncs[0] = nonce_commitment_other; ncs[0] = nonce_commitment_other;
ncs[1] = nonce_commitment; ncs[1] = nonce_commitment;
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2) == 1);
/* Trying to get the nonce without providing a message fails. */
CHECK(ecount == 0);
CHECK(secp256k1_musig_session_get_public_nonce(ctx_tmp, &session, signers, &nonce, ncs, 2, NULL) == 0);
CHECK(ecount == 1);
/* Providing a message should make get_public_nonce succeed. */
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2, msg) == 1);
/* Trying to set the message again fails. */
CHECK(ecount == 1);
CHECK(secp256k1_musig_session_get_public_nonce(ctx_tmp, &session, signers, &nonce, ncs, 2, msg) == 0);
CHECK(ecount == 2);
/* Check that it's working */
CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
CHECK(secp256k1_musig_session_combine_nonces(ctx, &session, signers, 2, NULL, NULL) == 1); CHECK(secp256k1_musig_session_combine_nonces(ctx, &session, signers, 2, NULL, NULL) == 1);
partial_sign = secp256k1_musig_partial_sign(ctx, &session, &partial_sig); CHECK(secp256k1_musig_partial_sign(ctx, &session, &partial_sig));
partial_verify = secp256k1_musig_partial_sig_verify(ctx, &session, &signers[0], partial_sig_other, &pks[0]); CHECK(secp256k1_musig_partial_sig_verify(ctx, &session, &signers[1], &partial_sig, &pks[1]));
if (msg != NULL) {
/* Return 1 if both succeeded */
return partial_sign && partial_verify;
}
/* Return 0 if both failed */
return partial_sign || partial_verify;
} }
/* Recreates a session with the given session_id, signers, pk, msg etc. parameters /* Recreates a session with the given session_id, signers, pk, msg etc. parameters
@ -495,10 +498,10 @@ int musig_state_machine_missing_combine_test(secp256k1_pubkey *pks, secp256k1_pu
secp256k1_schnorrsig sig; secp256k1_schnorrsig sig;
int partial_verify, sig_combine; int partial_verify, sig_combine;
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 0, sk) == 1); CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pk_hash, 2, 1, sk) == 1);
ncs[0] = nonce_commitment_other; ncs[0] = nonce_commitment_other;
ncs[1] = nonce_commitment; ncs[1] = nonce_commitment;
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
@ -553,16 +556,16 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
/* Set nonce commitments */ /* Set nonce commitments */
ncs[0] = nonce_commitment[0]; ncs[0] = nonce_commitment[0];
ncs[1] = nonce_commitment[1]; ncs[1] = nonce_commitment[1];
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
/* Changing a nonce commitment is not okay */ /* Changing a nonce commitment is not okay */
ncs[1] = (unsigned char*) "this isn't a nonce commitment..."; ncs[1] = (unsigned char*) "this isn't a nonce commitment...";
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2) == 0); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 0);
/* Repeating with the same nonce commitments is okay */ /* Repeating with the same nonce commitments is okay */
ncs[1] = nonce_commitment[1]; ncs[1] = nonce_commitment[1];
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
/* Get nonce for signer 1 */ /* Get nonce for signer 1 */
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2, NULL) == 1);
/* Set nonces */ /* Set nonces */
CHECK(secp256k1_musig_set_nonce(ctx, &signers0[0], &nonce[0]) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers0[0], &nonce[0]) == 1);
@ -597,12 +600,12 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
CHECK(musig_state_machine_diff_signer_msghash_test(msghash2, pk, &combined_pk, pk_hash, ncs, msg, &nonce[0], sk[1], session_id[1]) == 1); CHECK(musig_state_machine_diff_signer_msghash_test(msghash2, pk, &combined_pk, pk_hash, ncs, msg, &nonce[0], sk[1], session_id[1]) == 1);
CHECK(memcmp(msghash1, msghash2, 32) == 0); CHECK(memcmp(msghash1, msghash2, 32) == 0);
CHECK(secp256k1_musig_partial_sign(ctx, &session[1], &partial_sig[1]) == 1); CHECK(secp256k1_musig_partial_sign(ctx, &session[1], &partial_sig[1]) == 1);
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[1], &pk[1]) == 1); CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[1], &pk[1]) == 1);
/* Wrong signature */ /* Wrong signature */
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[0], &pk[1]) == 0); CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[0], &pk[1]) == 0);
/* Can't sign or verify until msg is set */ /* Can't get the public nonce until msg is set */
CHECK(musig_state_machine_missing_msg_test(pk, &combined_pk, pk_hash, nonce_commitment[0], &nonce[0], &partial_sig[0], sk[1], session_id[1], NULL) == 0); musig_state_machine_late_msg_test(pk, &combined_pk, pk_hash, nonce_commitment[0], &nonce[0], sk[1], session_id[1], msg);
CHECK(musig_state_machine_missing_msg_test(pk, &combined_pk, pk_hash, nonce_commitment[0], &nonce[0], &partial_sig[0], sk[1], session_id[1], msg) == 1);
/* Can't verify and combine partial sigs until nonces are combined */ /* Can't verify and combine partial sigs until nonces are combined */
CHECK(musig_state_machine_missing_combine_test(pk, &combined_pk, pk_hash, nonce_commitment[0], &nonce[0], &partial_sig[0], msg, sk[1], session_id[1], &partial_sig[1], 0) == 0); CHECK(musig_state_machine_missing_combine_test(pk, &combined_pk, pk_hash, nonce_commitment[0], &nonce[0], &partial_sig[0], msg, sk[1], session_id[1], &partial_sig[1], 0) == 0);
@ -676,10 +679,10 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
noncommit_b_ptr[1] = noncommit_b[1]; noncommit_b_ptr[1] = noncommit_b[1];
/* Step 2: Exchange nonces */ /* Step 2: Exchange nonces */
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_a[0], data_a, &pubnon_a[0], noncommit_a_ptr, 2)); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_a[0], data_a, &pubnon_a[0], noncommit_a_ptr, 2, NULL));
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_a[1], data_a, &pubnon_a[1], noncommit_a_ptr, 2)); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_a[1], data_a, &pubnon_a[1], noncommit_a_ptr, 2, NULL));
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_b[0], data_b, &pubnon_b[0], noncommit_b_ptr, 2)); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_b[0], data_b, &pubnon_b[0], noncommit_b_ptr, 2, NULL));
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_b[1], data_b, &pubnon_b[1], noncommit_b_ptr, 2)); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &musig_session_b[1], data_b, &pubnon_b[1], noncommit_b_ptr, 2, NULL));
CHECK(secp256k1_musig_set_nonce(ctx, &data_a[0], &pubnon_a[0])); CHECK(secp256k1_musig_set_nonce(ctx, &data_a[0], &pubnon_a[0]));
CHECK(secp256k1_musig_set_nonce(ctx, &data_a[1], &pubnon_a[1])); CHECK(secp256k1_musig_set_nonce(ctx, &data_a[1], &pubnon_a[1]));
CHECK(secp256k1_musig_set_nonce(ctx, &data_b[0], &pubnon_b[0])); CHECK(secp256k1_musig_set_nonce(ctx, &data_b[0], &pubnon_b[0]));
@ -777,8 +780,8 @@ void musig_tweak_test_helper(const secp256k1_pubkey* combined_pubkey, const unsi
/* Set nonce commitments */ /* Set nonce commitments */
ncs[0] = nonce_commitment[0]; ncs[0] = nonce_commitment[0];
ncs[1] = nonce_commitment[1]; ncs[1] = nonce_commitment[1];
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2) == 1); CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2, NULL) == 1);
/* Set nonces */ /* Set nonces */
CHECK(secp256k1_musig_set_nonce(ctx, &signers0[0], &nonce[0]) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers0[0], &nonce[0]) == 1);
CHECK(secp256k1_musig_set_nonce(ctx, &signers0[1], &nonce[1]) == 1); CHECK(secp256k1_musig_set_nonce(ctx, &signers0[1], &nonce[1]) == 1);