Skip to content

Commit 4619706

Browse files
committed
fixup! split counter mode from musig_nonce_gen
1 parent dfd9849 commit 4619706

File tree

5 files changed

+240
-73
lines changed

5 files changed

+240
-73
lines changed

examples/musig.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,19 @@ static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secr
102102

103103
for (i = 0; i < N_SIGNERS; i++) {
104104
unsigned char seckey[32];
105-
unsigned char session_id[32];
105+
unsigned char session_secrand[32];
106106
/* Create random session ID. It is absolutely necessary that the session ID
107107
* is unique for every call of secp256k1_musig_nonce_gen. Otherwise
108108
* it's trivial for an attacker to extract the secret key! */
109-
if (!fill_random(session_id, sizeof(session_id))) {
109+
if (!fill_random(session_secrand, sizeof(session_secrand))) {
110110
return 0;
111111
}
112112
if (!secp256k1_keypair_sec(ctx, seckey, &signer_secrets[i].keypair)) {
113113
return 0;
114114
}
115115
/* Initialize session and create secret nonce for signing and public
116116
* nonce to send to the other signers. */
117-
if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_id, seckey, &signer[i].pubkey, msg32, NULL, NULL)) {
117+
if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_secrand, seckey, &signer[i].pubkey, msg32, NULL, NULL)) {
118118
return 0;
119119
}
120120
pubnonces[i] = &signer[i].pubnonce;
@@ -132,7 +132,7 @@ static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secr
132132
return 0;
133133
}
134134
/* partial_sign will clear the secnonce by setting it to 0. That's because
135-
* you must _never_ reuse the secnonce (or use the same session_id to
135+
* you must _never_ reuse the secnonce (or use the same session_secrand to
136136
* create a secnonce). If you do, you effectively reuse the nonce and
137137
* leak the secret key. */
138138
if (!secp256k1_musig_partial_sign(ctx, &signer[i].partial_sig, &signer_secrets[i].secnonce, &signer_secrets[i].keypair, cache, &session)) {

include/secp256k1_musig.h

+66-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
#endif
99

1010
#include <stddef.h>
11+
#include <stdint.h>
1112

1213
/** This module implements BIP 327 "MuSig2 for BIP340-compatible
1314
* Multi-Signatures"
@@ -317,12 +318,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_twea
317318
* MuSig differs from regular Schnorr signing in that implementers _must_ take
318319
* special care to not reuse a nonce. This can be ensured by following these rules:
319320
*
320-
* 1. Each call to this function must have a UNIQUE session_id32 that must NOT BE
321+
* 1. Each call to this function must have a UNIQUE session_secrand32 that must NOT BE
321322
* REUSED in subsequent calls to this function.
322-
* If you do not provide a seckey, session_id32 _must_ be UNIFORMLY RANDOM
323-
* AND KEPT SECRET (even from other signers). If you do provide a seckey,
324-
* session_id32 can instead be a counter (that must never repeat!). However,
325-
* it is recommended to always choose session_id32 uniformly at random.
323+
* If you do not provide a seckey, session_secrand32 _must_ be UNIFORMLY RANDOM
324+
* AND KEPT SECRET (even from other signers).
326325
* 2. If you already know the seckey, message or aggregate public key
327326
* cache, they can be optionally provided to derive the nonce and increase
328327
* misuse-resistance. The extra_input32 argument can be used to provide
@@ -338,9 +337,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_twea
338337
* Args: ctx: pointer to a context object (not secp256k1_context_static)
339338
* Out: secnonce: pointer to a structure to store the secret nonce
340339
* pubnonce: pointer to a structure to store the public nonce
341-
* In: session_id32: a 32-byte session_id32 as explained above. Must be unique to this
342-
* call to secp256k1_musig_nonce_gen and must be uniformly random
343-
* unless you really know what you are doing.
340+
* In:
341+
* session_secrand32: a 32-byte session_secrand32 as explained above. Must be unique to this
342+
* call to secp256k1_musig_nonce_gen and must be uniformly random.
344343
* seckey: the 32-byte secret key that will later be used for signing, if
345344
* already known (can be NULL)
346345
* pubkey: public key of the signer creating the nonce. The secnonce
@@ -358,14 +357,72 @@ SECP256K1_API int secp256k1_musig_nonce_gen(
358357
const secp256k1_context *ctx,
359358
secp256k1_musig_secnonce *secnonce,
360359
secp256k1_musig_pubnonce *pubnonce,
361-
const unsigned char *session_id32,
360+
const unsigned char *session_secrand32,
362361
const unsigned char *seckey,
363362
const secp256k1_pubkey *pubkey,
364363
const unsigned char *msg32,
365364
const secp256k1_musig_keyagg_cache *keyagg_cache,
366365
const unsigned char *extra_input32
367366
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6);
368367

368+
369+
/** Alternative way to generate a nonce and start a signing session
370+
*
371+
* This function outputs a secret nonce that will be required for signing and a
372+
* corresponding public nonce that is intended to be sent to other signers.
373+
*
374+
* This function differs from `secp256k1_musig_nonce_gen` by accepting a
375+
* non-repeating counter value instead of a secret random value. This requires
376+
* the seckey argument to be mandatory.
377+
*
378+
* MuSig differs from regular Schnorr signing in that implementers _must_ take
379+
* special care to not reuse a nonce. This can be ensured by following these rules:
380+
*
381+
* 1. The nonrepeating_cnt argument must be a counter value that never
382+
* repeats, i.e., you must never call `secp256k1_musig_nonce_gen_counter`
383+
* twice with the same seckey and nonrepeating_cnt value.
384+
* 2. If you already know the seckey, message or aggregate public key
385+
* cache, they can be optionally provided to derive the nonce and increase
386+
* misuse-resistance. The extra_input32 argument can be used to provide
387+
* additional data that does not repeat in normal scenarios, such as the
388+
* current time.
389+
* 3. Avoid copying (or serializing) the secnonce. This reduces the possibility
390+
* that it is used more than once for signing.
391+
*
392+
* Remember that nonce reuse will leak the secret key!
393+
* Note that using the same seckey for multiple MuSig sessions is fine.
394+
*
395+
* Returns: 0 if the arguments are invalid and 1 otherwise
396+
* Args: ctx: pointer to a context object (not secp256k1_context_static)
397+
* Out: secnonce: pointer to a structure to store the secret nonce
398+
* pubnonce: pointer to a structure to store the public nonce
399+
* In:
400+
* nonrepeating_cnt: the value of a counter as explained above. Must be
401+
* unique to this call to secp256k1_musig_nonce_gen.
402+
* seckey: the 32-byte secret key that will later be used for signing
403+
* pubkey: public key of the signer creating the nonce. The secnonce
404+
* output of this function cannot be used to sign for any
405+
* other public key.
406+
* msg32: the 32-byte message that will later be signed, if already known
407+
* (can be NULL)
408+
* keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate
409+
* (and potentially tweaked) public key if already known
410+
* (can be NULL)
411+
* extra_input32: an optional 32-byte array that is input to the nonce
412+
* derivation function (can be NULL)
413+
*/
414+
SECP256K1_API int secp256k1_musig_nonce_gen_counter(
415+
const secp256k1_context *ctx,
416+
secp256k1_musig_secnonce *secnonce,
417+
secp256k1_musig_pubnonce *pubnonce,
418+
uint64_t nonrepeating_cnt,
419+
const unsigned char *seckey,
420+
const secp256k1_pubkey *pubkey,
421+
const unsigned char *msg32,
422+
const secp256k1_musig_keyagg_cache *keyagg_cache,
423+
const unsigned char *extra_input32
424+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
425+
369426
/** Aggregates the nonces of all signers into a single nonce
370427
*
371428
* This can be done by an untrusted party to reduce the communication

src/ctime_tests.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
190190
secp256k1_pubkey pk;
191191
const secp256k1_pubkey *pk_ptr[1];
192192
secp256k1_xonly_pubkey agg_pk;
193-
unsigned char session_id[32];
193+
unsigned char session_secrand[32];
194+
uint64_t nonrepeating_cnt = 0;
194195
secp256k1_musig_secnonce secnonce;
195196
secp256k1_musig_pubnonce pubnonce;
196197
const secp256k1_musig_pubnonce *pubnonce_ptr[1];
@@ -203,20 +204,25 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
203204
pk_ptr[0] = &pk;
204205
pubnonce_ptr[0] = &pubnonce;
205206
SECP256K1_CHECKMEM_DEFINE(key, 32);
206-
memcpy(session_id, key, sizeof(session_id));
207-
session_id[0] = session_id[0] + 1;
207+
memcpy(session_secrand, key, sizeof(session_secrand));
208+
session_secrand[0] = session_secrand[0] + 1;
208209
memcpy(extra_input, key, sizeof(extra_input));
209210
extra_input[0] = extra_input[0] + 2;
210211

211212
CHECK(secp256k1_keypair_create(ctx, &keypair, key));
212213
CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair));
213214
CHECK(secp256k1_musig_pubkey_agg(ctx, &agg_pk, &cache, pk_ptr, 1));
215+
214216
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
215-
SECP256K1_CHECKMEM_UNDEFINE(session_id, sizeof(session_id));
217+
SECP256K1_CHECKMEM_UNDEFINE(session_secrand, sizeof(session_secrand));
216218
SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input));
217-
ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_id, key, &pk, msg, &cache, extra_input);
219+
ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input);
220+
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
221+
CHECK(ret == 1);
222+
ret = secp256k1_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, nonrepeating_cnt, key, &pk, msg, &cache, extra_input);
218223
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
219224
CHECK(ret == 1);
225+
220226
CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1));
221227
/* Make sure that previous tests don't undefine msg. It's not used as a secret here. */
222228
SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg));

src/modules/musig/session_impl.h

+46-17
Original file line numberDiff line numberDiff line change
@@ -341,21 +341,21 @@ static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha)
341341
sha->bytes = 64;
342342
}
343343

344-
static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_id, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) {
344+
static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) {
345345
secp256k1_sha256 sha;
346346
unsigned char rand[32];
347347
unsigned char i;
348348
unsigned char msg_present;
349349

350350
if (seckey32 != NULL) {
351351
secp256k1_nonce_function_musig_sha256_tagged_aux(&sha);
352-
secp256k1_sha256_write(&sha, session_id, 32);
352+
secp256k1_sha256_write(&sha, session_secrand, 32);
353353
secp256k1_sha256_finalize(&sha, rand);
354354
for (i = 0; i < 32; i++) {
355355
rand[i] ^= seckey32[i];
356356
}
357357
} else {
358-
memcpy(rand, session_id, sizeof(rand));
358+
memcpy(rand, session_secrand, sizeof(rand));
359359
}
360360

361361
/* Subtract one from `sizeof` to avoid hashing the implicit null byte */
@@ -379,7 +379,7 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c
379379
}
380380
}
381381

382-
int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *session_id32, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
382+
int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
383383
secp256k1_keyagg_cache_internal cache_i;
384384
secp256k1_scalar k[2];
385385
secp256k1_ge nonce_pt[2];
@@ -392,24 +392,12 @@ int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secn
392392
int pk_serialize_success;
393393
int ret = 1;
394394

395-
VERIFY_CHECK(ctx != NULL);
396395
ARG_CHECK(secnonce != NULL);
397396
memset(secnonce, 0, sizeof(*secnonce));
398397
ARG_CHECK(pubnonce != NULL);
399398
memset(pubnonce, 0, sizeof(*pubnonce));
400-
ARG_CHECK(session_id32 != NULL);
401399
ARG_CHECK(pubkey != NULL);
402400
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
403-
if (seckey == NULL) {
404-
/* Check in constant time that the session_id is not 0 as a
405-
* defense-in-depth measure that may protect against a faulty RNG. */
406-
unsigned char acc = 0;
407-
for (i = 0; i < 32; i++) {
408-
acc |= session_id32[i];
409-
}
410-
ret &= !!acc;
411-
memset(&acc, 0, sizeof(acc));
412-
}
413401

414402
/* Check that the seckey is valid to be able to sign for it later. */
415403
if (seckey != NULL) {
@@ -439,7 +427,7 @@ int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secn
439427
(void) pk_serialize_success;
440428
#endif
441429

442-
secp256k1_nonce_function_musig(k, session_id32, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32);
430+
secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32);
443431
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0]));
444432
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1]));
445433
VERIFY_CHECK(!secp256k1_scalar_eq(&k[0], &k[1]));
@@ -458,6 +446,47 @@ int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secn
458446
return ret;
459447
}
460448

449+
int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *session_secrand32, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
450+
int ret = 1;
451+
unsigned char acc = 0;
452+
int i;
453+
454+
VERIFY_CHECK(ctx != NULL);
455+
ARG_CHECK(session_secrand32 != NULL);
456+
457+
/* Check in constant time that the session_secrand32 is not 0 as a
458+
* defense-in-depth measure that may protect against a faulty RNG. */
459+
for (i = 0; i < 32; i++) {
460+
acc |= session_secrand32[i];
461+
}
462+
ret &= !!acc;
463+
memset(&acc, 0, sizeof(acc));
464+
465+
/* We can declassify because branching on ret is only relevant when this
466+
* function called with an invalid session_secrand32 argument */
467+
secp256k1_declassify(ctx, &ret, sizeof(ret));
468+
if (ret == 0) {
469+
secp256k1_musig_secnonce_invalidate(ctx, secnonce, 1);
470+
return 0;
471+
}
472+
473+
return secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, session_secrand32, seckey, pubkey, msg32, keyagg_cache, extra_input32);
474+
}
475+
476+
int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, uint64_t nonrepeating_cnt, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
477+
unsigned char buf[32] = { 0 };
478+
int i;
479+
480+
VERIFY_CHECK(ctx != NULL);
481+
ARG_CHECK((seckey != NULL));
482+
483+
for (i = 0; i < 8; ++i) {
484+
buf[7 - i] = (nonrepeating_cnt >> (i * 8)) & 0xFF;
485+
}
486+
487+
return secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, pubkey, msg32, keyagg_cache, extra_input32);
488+
}
489+
461490
static int secp256k1_musig_sum_nonces(const secp256k1_context* ctx, secp256k1_gej *summed_nonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) {
462491
size_t i;
463492
int j;

0 commit comments

Comments
 (0)