Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

musig: use tagged hash for the list of pubkeys to aggregate #139

Merged
merged 2 commits into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/modules/musig/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,28 @@
#include "include/secp256k1_musig.h"
#include "hash.h"

/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */
static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);

sha->s[0] = 0xb399d5e0ul;
sha->s[1] = 0xc8fff302ul;
sha->s[2] = 0x6badac71ul;
sha->s[3] = 0x07c5b7f1ul;
sha->s[4] = 0x9701e2eful;
sha->s[5] = 0x2a72ecf8ul;
sha->s[6] = 0x201a4c7bul;
sha->s[7] = 0xab148a38ul;
sha->bytes = 64;
}

/* Computes ell = SHA256(pk[0], ..., pk[np-1]) */
static int secp256k1_musig_compute_ell(const secp256k1_context *ctx, unsigned char *ell, const secp256k1_xonly_pubkey * const* pk, size_t np) {
secp256k1_sha256 sha;
size_t i;

secp256k1_sha256_initialize(&sha);
secp256k1_musig_keyagglist_sha256(&sha);
for (i = 0; i < np; i++) {
unsigned char ser[32];
if (!secp256k1_xonly_pubkey_serialize(ctx, ser, pk[i])) {
Expand All @@ -31,7 +47,7 @@ static int secp256k1_musig_compute_ell(const secp256k1_context *ctx, unsigned ch

/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */
static void secp256k1_musig_sha256_init_tagged(secp256k1_sha256 *sha) {
static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);

sha->s[0] = 0x6ef02c5aul;
Expand All @@ -55,7 +71,7 @@ static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsig
if (secp256k1_fe_cmp_var(x, second_pk_x) == 0) {
secp256k1_scalar_set_int(r, 1);
} else {
secp256k1_musig_sha256_init_tagged(&sha);
secp256k1_musig_keyaggcoef_sha256(&sha);
secp256k1_sha256_write(&sha, ell, 32);
secp256k1_fe_get_b32(buf, x);
secp256k1_sha256_write(&sha, buf, 32);
Expand Down
2 changes: 1 addition & 1 deletion src/modules/musig/musig-spec.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ The algorithm ''KeyAgg(pk<sub>1..u</sub>)'' is defined as:
* Return ''bytes(S)''.

The algorithm ''HashKeys(pk<sub>1..u</sub>)'' is defined as:
* Return ''hash(pk<sub>1</sub> || pk<sub>2</sub> || ... || pk<sub>u</sub>)''
* Return ''hash<sub>KeyAgg list</sub>(pk<sub>1</sub> || pk<sub>2</sub> || ... || pk<sub>u</sub>)''

The algorithm ''IsSecond(pk<sub>1..u</sub>, i)'' is defined as:
* For ''j = 1 .. u'':
Expand Down
67 changes: 39 additions & 28 deletions src/modules/musig/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,18 +860,14 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_schnorrsig_verify(ctx, final_sig_a, msg32_a, &combined_pk_a) == 1);
}

/* Checks that hash initialized by secp256k1_musig_sha256_init_tagged has the
* expected state. */
void sha256_tag_test(void) {
char tag[18] = "KeyAgg coefficient";
void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) {
secp256k1_sha256 sha;
secp256k1_sha256 sha_tagged;
unsigned char buf[32];
unsigned char buf2[32];
size_t i;

secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, (unsigned char *) tag, sizeof(tag));
secp256k1_sha256_write(&sha, tag, taglen);
secp256k1_sha256_finalize(&sha, buf);
/* buf = SHA256("KeyAgg coefficient") */

Expand All @@ -882,17 +878,32 @@ void sha256_tag_test(void) {
CHECK((sha.bytes & 0x3F) == 0);

/* Compare with tagged SHA */
secp256k1_musig_sha256_init_tagged(&sha_tagged);
for (i = 0; i < 8; i++) {
CHECK(sha_tagged.s[i] == sha.s[i]);
CHECK(sha_tagged->s[i] == sha.s[i]);
}
secp256k1_sha256_write(&sha, buf, 32);
secp256k1_sha256_write(&sha_tagged, buf, 32);
secp256k1_sha256_write(sha_tagged, buf, 32);
secp256k1_sha256_finalize(&sha, buf);
secp256k1_sha256_finalize(&sha_tagged, buf2);
secp256k1_sha256_finalize(sha_tagged, buf2);
CHECK(memcmp(buf, buf2, 32) == 0);
}

/* Checks that the initialized tagged hashes initialized have the expected
* state. */
void sha256_tag_test(void) {
secp256k1_sha256 sha_tagged;
{
char tag[11] = "KeyAgg list";
secp256k1_musig_keyagglist_sha256(&sha_tagged);
sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag));
}
{
char tag[18] = "KeyAgg coefficient";
secp256k1_musig_keyaggcoef_sha256(&sha_tagged);
sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag));
}
}

/* Attempts to create a signature for the combined public key using given secret
* keys and pre_session. */
void musig_tweak_test_helper(const secp256k1_xonly_pubkey* combined_pubkey, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_pre_session *pre_session) {
Expand Down Expand Up @@ -1052,28 +1063,28 @@ void musig_test_vectors(void) {
};
const unsigned char combined_pk_expected[4][32] = {
{ /* 0 */
0xEA, 0x06, 0x7B, 0x01, 0x67, 0x24, 0x5A, 0x6F,
0xED, 0xB1, 0xB1, 0x22, 0xBB, 0x03, 0xAB, 0x7E,
0x5D, 0x48, 0x6C, 0x81, 0x83, 0x42, 0xE0, 0xE9,
0xB6, 0x41, 0x79, 0xAD, 0x32, 0x8D, 0x9D, 0x19,
0xE5, 0x83, 0x01, 0x40, 0x51, 0x21, 0x95, 0xD7,
0x4C, 0x83, 0x07, 0xE3, 0x96, 0x37, 0xCB, 0xE5,
0xFB, 0x73, 0x0E, 0xBE, 0xAB, 0x80, 0xEC, 0x51,
0x4C, 0xF8, 0x8A, 0x87, 0x7C, 0xEE, 0xEE, 0x0B,
},
{ /* 1 */
0x14, 0xE1, 0xF8, 0x3E, 0x9E, 0x25, 0x60, 0xFB,
0x2A, 0x6C, 0x04, 0x24, 0x55, 0x6C, 0x86, 0x8D,
0x9F, 0xB4, 0x63, 0x35, 0xD4, 0xF7, 0x8D, 0x22,
0x7D, 0x5D, 0x1D, 0x3C, 0x89, 0x90, 0x6F, 0x1E,
0xD7, 0x0C, 0xD6, 0x9A, 0x26, 0x47, 0xF7, 0x39,
0x09, 0x73, 0xDF, 0x48, 0xCB, 0xFA, 0x2C, 0xCC,
0x40, 0x7B, 0x8B, 0x2D, 0x60, 0xB0, 0x8C, 0x5F,
0x16, 0x41, 0x18, 0x5C, 0x79, 0x98, 0xA2, 0x90,
},
{ /* 2 */
0x70, 0x28, 0x8D, 0xF2, 0xB7, 0x60, 0x3D, 0xBE,
0xA0, 0xC7, 0xB7, 0x41, 0xDD, 0xAA, 0xB9, 0x46,
0x81, 0x14, 0x4E, 0x0B, 0x19, 0x08, 0x6C, 0x69,
0xB2, 0x34, 0x89, 0xE4, 0xF5, 0xB7, 0x01, 0x9A,
0x81, 0xA8, 0xB0, 0x93, 0x91, 0x2C, 0x9E, 0x48,
0x14, 0x08, 0xD0, 0x97, 0x76, 0xCE, 0xFB, 0x48,
0xAE, 0xB8, 0xB6, 0x54, 0x81, 0xB6, 0xBA, 0xAF,
0xB3, 0xC5, 0x81, 0x01, 0x06, 0x71, 0x7B, 0xEB,
},
{ /* 3 */
0x93, 0xEE, 0xD8, 0x24, 0xF2, 0x3C, 0x5A, 0xE1,
0xC1, 0x05, 0xE7, 0x31, 0x09, 0x97, 0x3F, 0xCD,
0x4A, 0xE3, 0x3A, 0x9F, 0xA0, 0x2F, 0x0A, 0xC8,
0x5A, 0x3E, 0x55, 0x89, 0x07, 0x53, 0xB0, 0x67,
0x2E, 0xB1, 0x88, 0x51, 0x88, 0x7E, 0x7B, 0xDC,
0x5E, 0x83, 0x0E, 0x89, 0xB1, 0x9D, 0xDB, 0xC2,
0x80, 0x78, 0xF1, 0xFA, 0x88, 0xAA, 0xD0, 0xAD,
0x01, 0xCA, 0x06, 0xFE, 0x4F, 0x80, 0x21, 0x0B,
},
};

Expand Down Expand Up @@ -1117,7 +1128,7 @@ void musig_test_vectors(void) {
memcpy(pk_ser_tmp[2], pk_ser[1], sizeof(pk_ser_tmp[2]));
memcpy(pk_ser_tmp[3], pk_ser[1], sizeof(pk_ser_tmp[3]));
has_second_pk = 1;
second_pk_idx = 3;
second_pk_idx = 2; /* second_pk_idx = 3 is equally valid */
break;
default:
CHECK(0);
Expand All @@ -1141,8 +1152,8 @@ void run_musig_tests(void) {
scriptless_atomic_swap(scratch);
musig_tweak_test(scratch);
}
musig_test_vectors();
sha256_tag_test();
musig_test_vectors();

secp256k1_scratch_space_destroy(ctx, scratch);
}
Expand Down