diff --git a/examples/frost.c b/examples/frost.c index 8a7e3b3bb..b74474f06 100644 --- a/examples/frost.c +++ b/examples/frost.c @@ -24,6 +24,7 @@ /* Threshold required in creating the aggregate signature */ #define THRESHOLD 3 +/* TODO: remove unused keypair */ struct signer_secrets { secp256k1_keypair keypair; secp256k1_frost_share agg_share; @@ -31,6 +32,7 @@ struct signer_secrets { unsigned char seed[32]; }; +/* TODO: remove unused vss_hash */ struct signer { secp256k1_pubkey pubshare; secp256k1_frost_pubnonce pubnonce; @@ -70,7 +72,7 @@ int create_keypair_and_seed(const secp256k1_context* ctx, struct signer_secrets } /* Create shares and coefficient commitments */ -int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, secp256k1_xonly_pubkey *pk) { +int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { int i, j; secp256k1_frost_share shares[N_SIGNERS][N_SIGNERS]; const secp256k1_pubkey *vss_commitments[N_SIGNERS]; @@ -101,7 +103,7 @@ int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_se assigned_shares[j] = &shares[j][i]; } /* Each participant aggregates the shares they received. */ - if (!secp256k1_frost_share_agg(ctx, &signer_secrets[i].agg_share, pk, assigned_shares, vss_commitments, poks, N_SIGNERS, THRESHOLD, signer[i].id)) { + if (!secp256k1_frost_share_agg(ctx, &signer_secrets[i].agg_share, assigned_shares, vss_commitments, poks, N_SIGNERS, THRESHOLD, signer[i].id)) { return 0; } for (j = 0; j < N_SIGNERS; j++) { @@ -130,10 +132,6 @@ int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pk, secp256k1_fr unsigned char ordinary_tweak[32] = "this could be a BIP32 tweak...."; unsigned char xonly_tweak[32] = "this could be a taproot tweak.."; - if (!secp256k1_frost_pubkey_tweak(ctx, cache, pk)) { - return 0; - } - /* Ordinary tweaking which, for example, allows deriving multiple child * public keys from a single aggregate key using BIP32 */ if (!secp256k1_frost_pubkey_ec_tweak_add(ctx, NULL, cache, ordinary_tweak)) { @@ -212,7 +210,7 @@ int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, st /* Signing communication round 1: Exchange nonces */ for (i = 0; i < THRESHOLD; i++) { signer_id = signers[i]; - if (!secp256k1_frost_nonce_process(ctx, &signer[signer_id].session, pubnonces, THRESHOLD, msg32, pk, signer[signer_id].id, ids, cache, NULL)) { + if (!secp256k1_frost_nonce_process(ctx, &signer[signer_id].session, pubnonces, THRESHOLD, msg32, signer[signer_id].id, ids, cache, NULL)) { return 0; } /* partial_sign will clear the secnonce by setting it to 0. That's because @@ -251,10 +249,12 @@ int main(void) { int i; struct signer_secrets signer_secrets[N_SIGNERS]; struct signer signers[N_SIGNERS]; + const secp256k1_pubkey *pubshares_ptr[N_SIGNERS]; secp256k1_xonly_pubkey pk; secp256k1_frost_tweak_cache cache; unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!"; unsigned char sig[64]; + const unsigned char *id_ptr[5]; /* Create a context for signing and verification */ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); @@ -264,10 +264,18 @@ int main(void) { printf("FAILED\n"); return 1; } + pubshares_ptr[i] = &signers[i].pubshare; + id_ptr[i] = signers[i].id; } printf("ok\n"); printf("Creating shares........."); - if (!create_shares(ctx, signer_secrets, signers, &pk)) { + if (!create_shares(ctx, signer_secrets, signers)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + printf("Generating public key..."); + if (!secp256k1_frost_pubkey_gen(ctx, &cache, pubshares_ptr, N_SIGNERS, id_ptr)) { printf("FAILED\n"); return 1; } diff --git a/include/secp256k1_frost.h b/include/secp256k1_frost.h index 459cea029..9e7c2e6fd 100644 --- a/include/secp256k1_frost.h +++ b/include/secp256k1_frost.h @@ -211,6 +211,7 @@ SECP256K1_API int secp256k1_frost_share_parse( * n_participants: the total number of participants * ids33: array of 33-byte participant IDs */ +/* TODO: rename this */ SECP256K1_API int secp256k1_frost_shares_gen( const secp256k1_context *ctx, secp256k1_frost_share *shares, @@ -252,14 +253,13 @@ SECP256K1_API int secp256k1_frost_shares_gen( SECP256K1_API int secp256k1_frost_share_agg( const secp256k1_context *ctx, secp256k1_frost_share *agg_share, - secp256k1_xonly_pubkey *agg_pk, const secp256k1_frost_share * const *shares, const secp256k1_pubkey * const *vss_commitments, const unsigned char * const *pok64s, size_t n_shares, size_t threshold, const unsigned char *id33 -) 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(9); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8); /** Verifies a share received during a key generation session * @@ -306,37 +306,18 @@ SECP256K1_API int secp256k1_frost_compute_pubshare( size_t n_participants ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); -/** Obtain the aggregate public key from a FROST x-only aggregate public key. - * - * This is only useful if you need the non-xonly public key, in particular for - * ordinary (non-xonly) tweaking or batch-verifying multiple key aggregations - * (not implemented). - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: ec_agg_pk: the FROST-aggregated public key. - * In: xonly_agg_pk: the aggregated x-only public key that is the output of - * `secp256k1_frost_share_agg` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_get( +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_gen( const secp256k1_context *ctx, - secp256k1_pubkey *ec_agg_pk, - const secp256k1_xonly_pubkey *xonly_agg_pk -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + secp256k1_frost_tweak_cache *cache, + const secp256k1_pubkey * const *pubshares, + size_t n_pubshares, + const unsigned char * const *ids33 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); -/** Initializes a tweak cache used for applying tweaks to a FROST key - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: tweak_cache: pointer to a frost_tweak_cache struct that is required - * for key tweaking - * In: agg_pk: the aggregated x-only public key that is the output of - * `secp256k1_frost_share_agg` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_tweak( +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_get( const secp256k1_context *ctx, - secp256k1_frost_tweak_cache *tweak_cache, - const secp256k1_xonly_pubkey *agg_pk + secp256k1_pubkey *pk, + const secp256k1_frost_tweak_cache *cache ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Apply ordinary "EC" tweaking to a public key in a given tweak_cache by @@ -490,22 +471,21 @@ SECP256K1_API int secp256k1_frost_nonce_gen( * n_pubnonces: number of elements in the pubnonces array. Must be * greater than 0. * msg32: the 32-byte message to sign - * agg_pk: the FROST-aggregated public key * myd_id33: the 33-byte ID of the participant who will use the * session for signing * ids33: array of the 33-byte participant IDs of the signers - * tweak_cache: pointer to frost_tweak_cache struct (can be NULL) + * tweak_cache: pointer to frost_tweak_cache struct * adaptor: optional pointer to an adaptor point encoded as a * public key if this signing session is part of an * adaptor signature protocol (can be NULL) */ +/* TODO(@jesseposner): const unsigned char * const *ids33 */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_nonce_process( const secp256k1_context *ctx, secp256k1_frost_session *session, const secp256k1_frost_pubnonce * const *pubnonces, size_t n_pubnonces, const unsigned char *msg32, - const secp256k1_xonly_pubkey *agg_pk, const unsigned char *my_id33, const unsigned char * const* ids33, const secp256k1_frost_tweak_cache *tweak_cache, @@ -529,7 +509,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_nonce_process( * In: agg_share: the aggregated share * session: pointer to the session that was created with * frost_nonce_process - * tweak_cache: pointer to frost_tweak_cache struct (can be NULL) + * tweak_cache: pointer to frost_tweak_cache struct */ SECP256K1_API int secp256k1_frost_partial_sign( const secp256k1_context *ctx, @@ -538,7 +518,7 @@ SECP256K1_API int secp256k1_frost_partial_sign( const secp256k1_frost_share *agg_share, const secp256k1_frost_session *session, const secp256k1_frost_tweak_cache *tweak_cache -) 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) SECP256K1_ARG_NONNULL(6); /** Verifies an individual signer's partial signature * @@ -565,7 +545,7 @@ SECP256K1_API int secp256k1_frost_partial_sign( * `secp256k1_frost_compute_pubshare` * session: pointer to the session that was created with * `frost_nonce_process` - * tweak_cache: pointer to frost_tweak_cache struct (can be NULL) + * tweak_cache: pointer to frost_tweak_cache struct */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_verify( const secp256k1_context *ctx, @@ -574,7 +554,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_verif const secp256k1_pubkey *pubshare, const secp256k1_frost_session *session, const secp256k1_frost_tweak_cache *tweak_cache -) 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) SECP256K1_ARG_NONNULL(6); /** Aggregates partial signatures * diff --git a/src/modules/frost/keygen.h b/src/modules/frost/keygen.h index fb17f3c67..45703303b 100644 --- a/src/modules/frost/keygen.h +++ b/src/modules/frost/keygen.h @@ -15,7 +15,10 @@ typedef struct { secp256k1_ge pk; + /* tweak is identical to value tacc[v] in the specification. */ secp256k1_scalar tweak; + /* parity_acc corresponds to gacc[v] in the spec. If gacc[v] is -1, + * parity_acc is 1. Otherwise, parity_acc is 0. */ int parity_acc; } secp256k1_tweak_cache_internal; @@ -25,4 +28,6 @@ static int secp256k1_frost_share_load(const secp256k1_context* ctx, secp256k1_sc static int secp256k1_frost_compute_indexhash(secp256k1_scalar *indexhash, const unsigned char *id33); +static int secp256k1_frost_lagrange_coefficient(secp256k1_scalar *r, const unsigned char * const *ids33, size_t n_participants, const unsigned char *my_id33); + #endif diff --git a/src/modules/frost/keygen_impl.h b/src/modules/frost/keygen_impl.h index 5a1d194ee..a6123fe53 100644 --- a/src/modules/frost/keygen_impl.h +++ b/src/modules/frost/keygen_impl.h @@ -34,7 +34,7 @@ static void secp256k1_tweak_cache_save(secp256k1_frost_tweak_cache *cache, secp2 unsigned char *ptr = cache->data; memcpy(ptr, secp256k1_frost_tweak_cache_magic, 4); ptr += 4; - secp256k1_point_save_ext(ptr, &cache_i->pk); + secp256k1_ge_to_bytes(ptr, &cache_i->pk); ptr += 64; *ptr = cache_i->parity_acc; ptr += 1; @@ -45,7 +45,7 @@ static int secp256k1_tweak_cache_load(const secp256k1_context* ctx, secp256k1_tw const unsigned char *ptr = cache->data; ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_frost_tweak_cache_magic, 4) == 0); ptr += 4; - secp256k1_point_load_ext(&cache_i->pk, ptr); + secp256k1_ge_from_bytes(&cache_i->pk, ptr); ptr += 64; cache_i->parity_acc = *ptr & 1; ptr += 1; @@ -242,6 +242,13 @@ typedef struct { size_t threshold; } secp256k1_frost_pubkey_combine_ecmult_data; +typedef struct { + const secp256k1_context *ctx; + const secp256k1_pubkey * const* pubshares; + const unsigned char * const *ids33; + size_t n_pubshares; +} secp256k1_frost_interpolate_pubkey_ecmult_data; + static int secp256k1_frost_verify_share_ecmult_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { secp256k1_frost_verify_share_ecmult_data *ctx = (secp256k1_frost_verify_share_ecmult_data *) data; if (!secp256k1_pubkey_load(ctx->ctx, pt, *(ctx->vss_commitment)+idx)) { @@ -268,6 +275,7 @@ static int secp256k1_frost_compute_pubshare_ecmult_callback(secp256k1_scalar *sc return 1; } +/* TODO: ecmult */ static int secp256k1_frost_pubkey_combine_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { secp256k1_frost_pubkey_combine_ecmult_data *ctx = (secp256k1_frost_pubkey_combine_ecmult_data *) data; @@ -276,6 +284,23 @@ static int secp256k1_frost_pubkey_combine_callback(secp256k1_scalar *sc, secp256 return secp256k1_pubkey_load(ctx->ctx, pt, &ctx->pks[idx][0]); } +static int secp256k1_frost_interpolate_pubkey_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { + secp256k1_frost_interpolate_pubkey_ecmult_data *ctx = (secp256k1_frost_interpolate_pubkey_ecmult_data *) data; + secp256k1_scalar l; + + if (!secp256k1_pubkey_load(ctx->ctx, pt, ctx->pubshares[idx])) { + return 0; + } + + if (!secp256k1_frost_lagrange_coefficient(&l, ctx->ids33, ctx->n_pubshares, ctx->ids33[idx])) { + return 0; + } + + *sc = l; + + return 1; +} + /* See draft-irtf-cfrg-frost-08#appendix-C.2 */ static int secp256k1_frost_vss_verify_internal(const secp256k1_context* ctx, size_t threshold, const unsigned char *id33, const secp256k1_scalar *share, const secp256k1_pubkey * const* vss_commitment) { secp256k1_scalar share_neg; @@ -326,9 +351,8 @@ int secp256k1_frost_share_verify(const secp256k1_context* ctx, size_t threshold, int secp256k1_frost_compute_pubshare(const secp256k1_context* ctx, secp256k1_pubkey *pubshare, size_t threshold, const unsigned char *id33, const secp256k1_pubkey * const* vss_commitments, size_t n_participants) { secp256k1_gej pkj; - secp256k1_ge pkp, tmp; + secp256k1_ge tmp; secp256k1_frost_compute_pubshare_ecmult_data compute_pubshare_ecmult_data; - secp256k1_frost_pubkey_combine_ecmult_data pubkey_combine_ecmult_data; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubshare != NULL); @@ -364,32 +388,12 @@ int secp256k1_frost_compute_pubshare(const secp256k1_context* ctx, secp256k1_pub return 0; } secp256k1_ge_set_gej(&tmp, &pkj); - - /* Combine pubkeys */ - pubkey_combine_ecmult_data.ctx = ctx; - pubkey_combine_ecmult_data.pks = vss_commitments; - pubkey_combine_ecmult_data.threshold = threshold; - - /* TODO: add scratch */ - if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_frost_pubkey_combine_callback, (void *) &pubkey_combine_ecmult_data, n_participants)) { - return 0; - } - secp256k1_ge_set_gej(&pkp, &pkj); - secp256k1_fe_normalize_var(&pkp.y); - if (secp256k1_fe_is_odd(&pkp.y)) { - secp256k1_ge_neg(&tmp, &tmp); - } - secp256k1_pubkey_save(pubshare, &tmp); return 1; } -int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_share *agg_share, secp256k1_xonly_pubkey *agg_pk, const secp256k1_frost_share * const* shares, const secp256k1_pubkey * const* vss_commitments, const unsigned char * const *pok64s, size_t n_shares, size_t threshold, const unsigned char *id33) { - secp256k1_frost_pubkey_combine_ecmult_data pubkey_combine_ecmult_data; - secp256k1_gej pkj; - secp256k1_ge pkp; - int pk_parity; +int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_share *agg_share, const secp256k1_frost_share * const* shares, const secp256k1_pubkey * const* vss_commitments, const unsigned char * const *pok64s, size_t n_shares, size_t threshold, const unsigned char *id33) { secp256k1_scalar acc; size_t i; int ret = 1; @@ -399,8 +403,6 @@ int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_shar VERIFY_CHECK(ctx != NULL); ARG_CHECK(agg_share != NULL); memset(agg_share, 0, sizeof(*agg_share)); - ARG_CHECK(agg_pk != NULL); - memset(agg_pk, 0, sizeof(*agg_pk)); ARG_CHECK(shares != NULL); ARG_CHECK(pok64s != NULL); ARG_CHECK(vss_commitments != NULL); @@ -437,61 +439,67 @@ int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_shar ret &= secp256k1_frost_vss_verify_internal(ctx, threshold, id33, &share_i, &vss_commitments[i]); secp256k1_scalar_add(&acc, &acc, &share_i); } - - /* Combine pubkeys */ - pubkey_combine_ecmult_data.ctx = ctx; - pubkey_combine_ecmult_data.pks = vss_commitments; - pubkey_combine_ecmult_data.threshold = threshold; - - /* TODO: add scratch */ - if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_frost_pubkey_combine_callback, (void *) &pubkey_combine_ecmult_data, n_shares)) { - return 0; - } - - secp256k1_ge_set_gej(&pkp, &pkj); - secp256k1_fe_normalize_var(&pkp.y); - pk_parity = secp256k1_extrakeys_ge_even_y(&pkp); - secp256k1_xonly_pubkey_save(agg_pk, &pkp); - - /* Invert the aggregate share if the combined pubkey has an odd Y coordinate. */ - if (pk_parity == 1) { - secp256k1_scalar_negate(&acc, &acc); - } secp256k1_frost_share_save(agg_share, &acc); return ret; } -int secp256k1_frost_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *ec_pk, const secp256k1_xonly_pubkey *xonly_pk) { - secp256k1_ge pk; - +/* int secp256k1_frost_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *pk, const secp256k1_frost_tweak_cache *cache) { */ + /* secp256k1_tweak_cache_internal cache_i; */ + /* VERIFY_CHECK(ctx != NULL); */ + /* ARG_CHECK(pk != NULL); */ + /* memset(pk, 0, sizeof(*pk)); */ + /* printf("1"); */ + /* ARG_CHECK(cache != NULL); */ + /* printf("2"); */ + + /* if(!secp256k1_tweak_cache_load(ctx, &cache_i, cache)) { */ + /* return 0; */ + /* } */ + /* secp256k1_pubkey_save(pk, &cache_i.pk); */ + /* return 1; */ +/* } */ + +int secp256k1_frost_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *agg_pk, const secp256k1_frost_tweak_cache *keyagg_cache) { + secp256k1_tweak_cache_internal cache_i; VERIFY_CHECK(ctx != NULL); - ARG_CHECK(ec_pk != NULL); - memset(ec_pk, 0, sizeof(*ec_pk)); - ARG_CHECK(xonly_pk != NULL); + ARG_CHECK(agg_pk != NULL); + memset(agg_pk, 0, sizeof(*agg_pk)); + ARG_CHECK(keyagg_cache != NULL); + /* if (keyagg_cache == NULL) { */ + /* return 0; */ + /* } */ - /* The output of keygen is an aggregated public key that *always* has an - * even Y coordinate. */ - if (!secp256k1_xonly_pubkey_load(ctx, &pk, xonly_pk)) { + if(!secp256k1_tweak_cache_load(ctx, &cache_i, keyagg_cache)) { return 0; } - secp256k1_pubkey_save(ec_pk, &pk); + secp256k1_pubkey_save(agg_pk, &cache_i.pk); return 1; } -int secp256k1_frost_pubkey_tweak(const secp256k1_context* ctx, secp256k1_frost_tweak_cache *tweak_cache, const secp256k1_xonly_pubkey *pk) { +int secp256k1_frost_pubkey_gen(const secp256k1_context* ctx, secp256k1_frost_tweak_cache *cache, const secp256k1_pubkey * const *pubshares, size_t n_pubshares, const unsigned char * const *ids33) { + secp256k1_gej pkj; + secp256k1_frost_interpolate_pubkey_ecmult_data interpolate_pubkey_ecmult_data; secp256k1_tweak_cache_internal cache_i = { 0 }; VERIFY_CHECK(ctx != NULL); - ARG_CHECK(tweak_cache != NULL); - ARG_CHECK(pk != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(cache != NULL); + ARG_CHECK(pubshares != NULL); + ARG_CHECK(ids33 != NULL); + ARG_CHECK(n_pubshares > 1); - /* The output of keygen is an aggregated public key that *always* has an - * even Y coordinate. */ - if (!secp256k1_xonly_pubkey_load(ctx, &cache_i.pk, pk)) { + interpolate_pubkey_ecmult_data.ctx = ctx; + interpolate_pubkey_ecmult_data.pubshares = pubshares; + interpolate_pubkey_ecmult_data.ids33 = ids33; + interpolate_pubkey_ecmult_data.n_pubshares = n_pubshares; + + /* TODO: add scratch */ + if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_frost_interpolate_pubkey_callback, (void *) &interpolate_pubkey_ecmult_data, n_pubshares)) { return 0; } - secp256k1_tweak_cache_save(tweak_cache, &cache_i); + secp256k1_ge_set_gej(&cache_i.pk, &pkj); + secp256k1_tweak_cache_save(cache, &cache_i); return 1; } @@ -540,4 +548,37 @@ int secp256k1_frost_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256 return secp256k1_frost_pubkey_tweak_add_internal(ctx, output_pubkey, tweak_cache, tweak32, 1); } +static int secp256k1_frost_lagrange_coefficient(secp256k1_scalar *r, const unsigned char * const *ids33, size_t n_participants, const unsigned char *my_id33) { + size_t i; + secp256k1_scalar num; + secp256k1_scalar den; + secp256k1_scalar party_idx; + + secp256k1_scalar_set_int(&num, 1); + secp256k1_scalar_set_int(&den, 1); + if (!secp256k1_frost_compute_indexhash(&party_idx, my_id33)) { + return 0; + } + for (i = 0; i < n_participants; i++) { + secp256k1_scalar mul; + + if (!secp256k1_frost_compute_indexhash(&mul, ids33[i])) { + return 0; + } + if (secp256k1_scalar_eq(&mul, &party_idx)) { + continue; + } + + secp256k1_scalar_negate(&mul, &mul); + secp256k1_scalar_mul(&num, &num, &mul); + secp256k1_scalar_add(&mul, &mul, &party_idx); + secp256k1_scalar_mul(&den, &den, &mul); + } + + secp256k1_scalar_inverse_var(&den, &den); + secp256k1_scalar_mul(r, &num, &den); + + return 1; +} + #endif diff --git a/src/modules/frost/session_impl.h b/src/modules/frost/session_impl.h index bba1f7095..89dffd515 100644 --- a/src/modules/frost/session_impl.h +++ b/src/modules/frost/session_impl.h @@ -373,62 +373,27 @@ static int secp256k1_frost_nonce_process_internal(const secp256k1_context* ctx, } /* fin_nonce = aggnonce[0] + b*aggnonce[1] */ secp256k1_scalar_set_b32(b, noncehash, NULL); + secp256k1_gej_set_infinity(&fin_nonce_ptj); secp256k1_ecmult(&fin_nonce_ptj, &aggnoncej[1], b, NULL); secp256k1_gej_add_ge_var(&fin_nonce_ptj, &fin_nonce_ptj, &aggnonce[0], NULL); secp256k1_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj); - if (secp256k1_ge_is_infinity(&fin_nonce_pt)) { - /* unreachable with overwhelming probability */ - return 0; + fin_nonce_pt = secp256k1_ge_const_g; } + /* fin_nonce_pt is not the point at infinity */ secp256k1_fe_normalize_var(&fin_nonce_pt.x); secp256k1_fe_get_b32(fin_nonce, &fin_nonce_pt.x); - secp256k1_fe_normalize_var(&fin_nonce_pt.y); *fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y); return 1; } -static int secp256k1_frost_lagrange_coefficient(secp256k1_scalar *r, const unsigned char * const *ids33, size_t n_participants, const unsigned char *my_id33) { - size_t i; - secp256k1_scalar num; - secp256k1_scalar den; - secp256k1_scalar party_idx; - - secp256k1_scalar_set_int(&num, 1); - secp256k1_scalar_set_int(&den, 1); - if (!secp256k1_frost_compute_indexhash(&party_idx, my_id33)) { - return 0; - } - for (i = 0; i < n_participants; i++) { - secp256k1_scalar mul; - - if (!secp256k1_frost_compute_indexhash(&mul, ids33[i])) { - return 0; - } - if (secp256k1_scalar_eq(&mul, &party_idx)) { - continue; - } - - secp256k1_scalar_negate(&mul, &mul); - secp256k1_scalar_mul(&num, &num, &mul); - secp256k1_scalar_add(&mul, &mul, &party_idx); - secp256k1_scalar_mul(&den, &den, &mul); - } - - secp256k1_scalar_inverse_var(&den, &den); - secp256k1_scalar_mul(r, &num, &den); - - return 1; -} - -int secp256k1_frost_nonce_process(const secp256k1_context* ctx, secp256k1_frost_session *session, const secp256k1_frost_pubnonce * const* pubnonces, size_t n_pubnonces, const unsigned char *msg32, const secp256k1_xonly_pubkey *pk, const unsigned char *my_id33, const unsigned char * const *ids33, const secp256k1_frost_tweak_cache *tweak_cache, const secp256k1_pubkey *adaptor) { - secp256k1_ge aggnonce_pt[2]; +int secp256k1_frost_nonce_process(const secp256k1_context* ctx, secp256k1_frost_session *session, const secp256k1_frost_pubnonce * const* pubnonces, size_t n_pubnonces, const unsigned char *msg32, const unsigned char *my_id33, const unsigned char * const *ids33, const secp256k1_frost_tweak_cache *tweak_cache, const secp256k1_pubkey *adaptor) { + secp256k1_tweak_cache_internal cache_i; secp256k1_gej aggnonce_ptj[2]; unsigned char fin_nonce[32]; secp256k1_frost_session_internal session_i = { 0 }; unsigned char pk32[32]; - size_t i; secp256k1_scalar l; VERIFY_CHECK(ctx != NULL); @@ -437,37 +402,17 @@ int secp256k1_frost_nonce_process(const secp256k1_context* ctx, secp256k1_frost_ ARG_CHECK(pubnonces != NULL); ARG_CHECK(ids33 != NULL); ARG_CHECK(my_id33 != NULL); - ARG_CHECK(pk != NULL); + ARG_CHECK(tweak_cache != NULL); ARG_CHECK(n_pubnonces > 1); - if (!secp256k1_xonly_pubkey_serialize(ctx, pk32, pk)) { + if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { return 0; } + secp256k1_fe_get_b32(pk32, &cache_i.pk.x); if (!secp256k1_frost_sum_nonces(ctx, aggnonce_ptj, pubnonces, n_pubnonces)) { return 0; } - for (i = 0; i < 2; i++) { - if (secp256k1_gej_is_infinity(&aggnonce_ptj[i])) { - /* There must be at least one dishonest signer. If we would return 0 - here, we will never be able to determine who it is. Therefore, we - should continue such that the culprit is revealed when collecting - and verifying partial signatures. - However, dealing with the point at infinity (loading, - de-/serializing) would require a lot of extra code complexity. - Instead, we set the aggregate nonce to some arbitrary point (the - generator). This is secure, because it only restricts the - abilities of the attacker: an attacker that forces the sum of - nonces to be infinity by sending some maliciously generated nonce - pairs can be turned into an attacker that forces the sum to be - the generator (by simply adding the generator to one of the - malicious nonces), and this does not change the winning condition - of the EUF-CMA game. */ - aggnonce_pt[i] = secp256k1_ge_const_g; - } else { - secp256k1_ge_set_gej(&aggnonce_pt[i], &aggnonce_ptj[i]); - } - } /* Add public adaptor to nonce */ if (adaptor != NULL) { secp256k1_ge adaptorp; @@ -484,19 +429,13 @@ int secp256k1_frost_nonce_process(const secp256k1_context* ctx, secp256k1_frost_ /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ secp256k1_scalar_set_int(&session_i.s_part, 0); - if (tweak_cache != NULL) { - secp256k1_tweak_cache_internal cache_i; - if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { - return 0; - } - if (!secp256k1_scalar_is_zero(&cache_i.tweak)) { - secp256k1_scalar e_tmp; - secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); - if (secp256k1_fe_is_odd(&cache_i.pk.y)) { - secp256k1_scalar_negate(&e_tmp, &e_tmp); - } - secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &e_tmp); + if (!secp256k1_scalar_is_zero(&cache_i.tweak)) { + secp256k1_scalar e_tmp; + secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); + if (secp256k1_fe_is_odd(&cache_i.pk.y)) { + secp256k1_scalar_negate(&e_tmp, &e_tmp); } + secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &e_tmp); } /* Update the challenge by multiplying the Lagrange coefficient to prepare * for signing. */ @@ -519,6 +458,7 @@ int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_p secp256k1_scalar sk; secp256k1_scalar k[2]; secp256k1_scalar s; + secp256k1_tweak_cache_internal cache_i; secp256k1_frost_session_internal session_i; int ret; @@ -537,26 +477,29 @@ int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_p ARG_CHECK(partial_sig != NULL); ARG_CHECK(share != NULL); + ARG_CHECK(tweak_cache != NULL); ARG_CHECK(session != NULL); if (!secp256k1_frost_share_load(ctx, &sk, share)) { secp256k1_frost_partial_sign_clear(&sk, k); return 0; } - if (!secp256k1_frost_session_load(ctx, &session_i, session)) { + if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { secp256k1_frost_partial_sign_clear(&sk, k); return 0; } - if (tweak_cache != NULL) { - secp256k1_tweak_cache_internal cache_i; - if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { - secp256k1_frost_partial_sign_clear(&sk, k); - return 0; - } - if (secp256k1_fe_is_odd(&cache_i.pk.y) != cache_i.parity_acc) { - secp256k1_scalar_negate(&sk, &sk); - } + /* Negate sk if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. + * This corresponds to the line "Let d = g⋅gacc⋅d' mod n" in the + * specification. */ + if ((secp256k1_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc)) { + secp256k1_scalar_negate(&sk, &sk); + } + + if (!secp256k1_frost_session_load(ctx, &session_i, session)) { + secp256k1_frost_partial_sign_clear(&sk, k); + return 0; } if (session_i.fin_nonce_parity) { @@ -575,6 +518,7 @@ int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_p } int secp256k1_frost_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_frost_partial_sig *partial_sig, const secp256k1_frost_pubnonce *pubnonce, const secp256k1_pubkey *pubshare, const secp256k1_frost_session *session, const secp256k1_frost_tweak_cache *tweak_cache) { + secp256k1_tweak_cache_internal cache_i; secp256k1_frost_session_internal session_i; secp256k1_scalar e, s; secp256k1_gej pkj; @@ -587,6 +531,7 @@ int secp256k1_frost_partial_sig_verify(const secp256k1_context* ctx, const secp2 ARG_CHECK(partial_sig != NULL); ARG_CHECK(pubnonce != NULL); ARG_CHECK(pubshare != NULL); + ARG_CHECK(tweak_cache != NULL); ARG_CHECK(session != NULL); if (!secp256k1_frost_session_load(ctx, &session_i, session)) { @@ -605,23 +550,25 @@ int secp256k1_frost_partial_sig_verify(const secp256k1_context* ctx, const secp2 if (!secp256k1_pubkey_load(ctx, &pkp, pubshare)) { return 0; } + if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { + return 0; + } secp256k1_scalar_set_int(&e, 1); - if (tweak_cache != NULL) { - secp256k1_tweak_cache_internal cache_i; - if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { - return 0; - } - if (secp256k1_fe_is_odd(&cache_i.pk.y) - != cache_i.parity_acc) { - secp256k1_scalar_negate(&e, &e); - } + /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. + * This corresponds to the line "Let g' = g⋅gacc mod n" and the multiplication "g'⋅e" + * in the specification. */ + if (secp256k1_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc) { + secp256k1_scalar_negate(&e, &e); } secp256k1_scalar_mul(&e, &e, &session_i.challenge); if (!secp256k1_frost_partial_sig_load(ctx, &s, partial_sig)) { return 0; } + + /* TODO: consider making this more like musig and compute coefficient separaetly in partial sign and verify */ /* Compute -s*G + e*pkj + rj (e already includes the lagrange coefficient l) */ secp256k1_scalar_negate(&s, &s); secp256k1_gej_set_ge(&pkj, &pkp); diff --git a/src/modules/frost/tests_impl.h b/src/modules/frost/tests_impl.h index 27719d3c3..fe18a8977 100644 --- a/src/modules/frost/tests_impl.h +++ b/src/modules/frost/tests_impl.h @@ -44,7 +44,8 @@ void frost_simple_test(void) { secp256k1_pubkey vss_commitment[5][3]; const secp256k1_pubkey *vss_ptr[5]; unsigned char pok[5][64]; - secp256k1_xonly_pubkey agg_pk; + secp256k1_xonly_pubkey pk_xonly; + secp256k1_pubkey pk; unsigned char buf[5][32]; secp256k1_frost_share shares[5][5]; const secp256k1_frost_share *share_ptr[5]; @@ -59,6 +60,8 @@ void frost_simple_test(void) { unsigned char id[5][33]; const unsigned char *id_ptr[5]; const unsigned char *pok_ptr[5]; + const secp256k1_pubkey *pubshare_ptr[5]; + secp256k1_frost_tweak_cache cache; for (i = 0; i < 5; i++) { secp256k1_testrand256(buf[i]); @@ -68,6 +71,7 @@ void frost_simple_test(void) { partial_sig_ptr[i] = &partial_sig[i]; id_ptr[i] = id[i]; pok_ptr[i] = pok[i]; + pubshare_ptr[i] = &pubshare[i]; CHECK(frost_create_pk(id[i], sk[i])); } @@ -78,10 +82,11 @@ void frost_simple_test(void) { for (j = 0; j < 5; j++) { share_ptr[j] = &shares[j][i]; CHECK(secp256k1_frost_share_verify(CTX, 3, id_ptr[i], share_ptr[j], &vss_ptr[j]) == 1); - CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[j], 3, id_ptr[j], vss_ptr, 5) == 1); } - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); + CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[i], 3, id_ptr[i], vss_ptr, 5) == 1); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); } + CHECK(secp256k1_frost_pubkey_gen(CTX, &cache, pubshare_ptr, 5, id_ptr) == 1); secp256k1_testrand256(msg); for (i = 0; i < 3; i++) { @@ -90,12 +95,14 @@ void frost_simple_test(void) { CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[i], &pubnonce[i], buf[i], &agg_share[i], NULL, NULL, NULL) == 1); } for (i = 0; i < 3; i++) { - CHECK(secp256k1_frost_nonce_process(CTX, &session, pubnonce_ptr, 3, msg, &agg_pk, id_ptr[i], id_ptr, NULL, NULL) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[i], &secnonce[i], &agg_share[i], &session, NULL) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pubshare[i], &session, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session, pubnonce_ptr, 3, msg, id_ptr[i], id_ptr, &cache, NULL) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[i], &secnonce[i], &agg_share[i], &session, &cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pubshare[i], &session, &cache) == 1); } CHECK(secp256k1_frost_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 3) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); + CHECK(secp256k1_frost_pubkey_get(CTX, &pk, &cache) == 1); + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &pk_xonly, NULL, &pk) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &pk_xonly) == 1); } void frost_pubnonce_summing_to_inf(secp256k1_frost_pubnonce *pubnonce) { @@ -152,8 +159,8 @@ void frost_api_tests(void) { secp256k1_frost_pubnonce invalid_pubnonce; const secp256k1_frost_pubnonce *invalid_pubnonce_ptr[5]; unsigned char msg[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_pubkey full_agg_pk; + secp256k1_pubkey pk; + secp256k1_xonly_pubkey pk_xonly; secp256k1_frost_tweak_cache tweak_cache; secp256k1_frost_tweak_cache invalid_tweak_cache; secp256k1_frost_session session[5]; @@ -181,6 +188,7 @@ void frost_api_tests(void) { const unsigned char *id_ptr[5]; const unsigned char *pok_ptr[5]; const unsigned char *invalid_pok_ptr[5]; + const secp256k1_pubkey *pubshare_ptr[5]; /** setup **/ memset(max64, 0xff, sizeof(max64)); @@ -210,6 +218,7 @@ void frost_api_tests(void) { invalid_partial_sig_ptr[i] = &partial_sig[i]; id_ptr[i] = id[i]; pok_ptr[i] = pok[i]; + pubshare_ptr[i] = &pubshare[i]; invalid_pok_ptr[i] = pok[i]; secp256k1_testrand256(session_id[i]); secp256k1_testrand256(seed[i]); @@ -264,48 +273,34 @@ void frost_api_tests(void) { invalid_share_ptr[j] = &shares[j][i]; } invalid_share_ptr[0] = &invalid_share; - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, invalid_pok_ptr, 5, 3, id_ptr[i]) == 0); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, invalid_pok_ptr, 5, 3, id_ptr[i]) == 0); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, NULL, &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, NULL, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, NULL, pok_ptr, 5, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, invalid_vss_ptr, pok_ptr, 5, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, invalid_vss_ptr, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, NULL, 5, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, NULL, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, NULL)); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], invalid_share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, invalid_share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 0, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 0, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, vss_ptr, pok_ptr, 0, 3, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, pok_ptr, 0, 3, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 0, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 0, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, NULL, pok_ptr, 5, 0, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, pok_ptr, 5, 0, id_ptr[i])); + CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, NULL, 5, 0, id_ptr[i])); CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, NULL, 5, 0, id_ptr[i])); - CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); - CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); } /* Share verification */ @@ -342,29 +337,28 @@ void frost_api_tests(void) { CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[0], 3, id_ptr[0], vss_ptr, 5) == 1); CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[1], 3, id_ptr[1], vss_ptr, 5) == 1); CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[2], 3, id_ptr[2], vss_ptr, 5) == 1); + CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[3], 3, id_ptr[3], vss_ptr, 5) == 1); + CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[4], 3, id_ptr[4], vss_ptr, 5) == 1); - /* pubkey_get */ - CHECK(secp256k1_frost_pubkey_get(CTX, &full_agg_pk, &agg_pk) == 1); - CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_get(CTX, NULL, &agg_pk)); - CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_get(CTX, &full_agg_pk, NULL)); - CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros68, sizeof(full_agg_pk)) == 0); - - /** Tweaking **/ - - /* pubkey_tweak */ - CHECK(secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, &agg_pk) == 1); - CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_tweak(CTX, NULL, &agg_pk)); - CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, &invalid_pk)); + /* pubkey_gen */ + CHECK(secp256k1_frost_pubkey_gen(CTX, &tweak_cache, pubshare_ptr, 5, id_ptr) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, NULL, pubshare_ptr, 5, id_ptr)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, &tweak_cache, NULL, 5, id_ptr)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, &tweak_cache, pubshare_ptr, 0, id_ptr)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, &tweak_cache, pubshare_ptr, 5, NULL)); - CHECK(secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, &agg_pk) == 1); + /* pubkey_get */ + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_get(CTX, NULL, &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_get(CTX, &pk, NULL)); + CHECK(secp256k1_memcmp_var(&pk, zeros68, sizeof(pk)) == 0); + CHECK(secp256k1_frost_pubkey_get(CTX, &pk, &tweak_cache) == 1); /* tweak_add */ { int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_tweak_cache *tweak_cache, const unsigned char *tweak32); tweak_func[0] = secp256k1_frost_pubkey_ec_tweak_add; tweak_func[1] = secp256k1_frost_pubkey_xonly_tweak_add; - CHECK(secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, &agg_pk) == 1); + for (i = 0; i < 2; i++) { secp256k1_pubkey tmp_output_pk; secp256k1_frost_tweak_cache tmp_tweak_cache = tweak_cache; @@ -391,26 +385,27 @@ void frost_api_tests(void) { } /** Session creation **/ - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &agg_pk, max64) == 1); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_frost_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &agg_pk, max64)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, NULL, &pubnonce[0], session_id[0], &agg_share[0], msg, &agg_pk, max64)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], NULL, session_id[0], &agg_share[0], msg, &agg_pk, max64)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, &agg_share[0], msg, &agg_pk, max64)); + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &pk_xonly, NULL, &pk) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &pk_xonly, max64) == 1); + CHECK_ILLEGAL(STATIC_CTX, secp256k1_frost_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &pk_xonly, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, NULL, &pubnonce[0], session_id[0], &agg_share[0], msg, &pk_xonly, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], NULL, session_id[0], &agg_share[0], msg, &pk_xonly, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, &agg_share[0], msg, &pk_xonly, max64)); CHECK(frost_memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); /* no seckey and session_id is 0 */ - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros68, NULL, msg, &agg_pk, max64) == 0); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros68, NULL, msg, &pk_xonly, max64) == 0); CHECK(frost_memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); /* session_id 0 is fine when a seckey is provided */ - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros68, &agg_share[0], msg, &agg_pk, max64) == 1); - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, msg, &agg_pk, max64) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros68, &agg_share[0], msg, &pk_xonly, max64) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, msg, &pk_xonly, max64) == 1); /* invalid agg_share */ - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &invalid_share, msg, &agg_pk, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &invalid_share, msg, &pk_xonly, max64)); CHECK(frost_memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], NULL, &agg_pk, max64) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], NULL, &pk_xonly, max64) == 1); CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, NULL, max64) == 1); CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &invalid_pk, max64)); CHECK(frost_memcmp_and_randomize(secnonce[0].data, zeros68, sizeof(secnonce[0].data)) == 0); - CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &agg_pk, NULL) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &pk_xonly, NULL) == 1); /* Every in-argument except session_id can be NULL */ CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, NULL, NULL, NULL) == 1); @@ -440,23 +435,22 @@ void frost_api_tests(void) { } /** Process nonces **/ - CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor) == 1); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, NULL, pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], NULL, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 0, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], invalid_pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, NULL, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, NULL, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, NULL, id_ptr, &tweak_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], NULL, &tweak_cache, &adaptor)); - CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, NULL, &adaptor) == 1); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &invalid_tweak_cache, &adaptor)); - CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, (secp256k1_pubkey *)&invalid_pk)); - - CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[0], id_ptr, &tweak_cache, &adaptor) == 1); - CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[1], id_ptr, &tweak_cache, &adaptor) == 1); - CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, &agg_pk, id_ptr[2], id_ptr, &tweak_cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, NULL, pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], NULL, 3, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 0, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], invalid_pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, NULL, id_ptr[0], id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, NULL, id_ptr, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], NULL, &tweak_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, NULL, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &invalid_tweak_cache, &adaptor)); + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, NULL) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, (secp256k1_pubkey *)&invalid_pk)); + + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &tweak_cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, id_ptr[1], id_ptr, &tweak_cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, id_ptr[2], id_ptr, &tweak_cache, &adaptor) == 1); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &tweak_cache) == 1); @@ -476,7 +470,7 @@ void frost_api_tests(void) { memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &invalid_session, &tweak_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], NULL) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], NULL)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &invalid_tweak_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); @@ -512,7 +506,7 @@ void frost_api_tests(void) { CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_vss_pk, &session[0], &tweak_cache)); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], NULL, &tweak_cache)); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &invalid_session, &tweak_cache)); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], NULL) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], NULL)); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &invalid_tweak_cache)); CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &tweak_cache) == 1); @@ -547,10 +541,10 @@ void frost_api_tests(void) { /* sig and pre_sig argument point to the same location */ memcpy(final_sig, pre_sig, sizeof(final_sig)); CHECK(secp256k1_frost_adapt(CTX, final_sig, final_sig, sec_adaptor, nonce_parity) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &pk_xonly) == 1); CHECK(secp256k1_frost_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &pk_xonly) == 1); /** Secret adaptor can be extracted from signature */ CHECK(secp256k1_frost_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, nonce_parity) == 1); @@ -679,9 +673,9 @@ void frost_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const secp256 CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_id[1], sr1, NULL, NULL, NULL) == 1); CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[2], &pubnonce[2], session_id[2], sr2, NULL, NULL, NULL) == 1); - CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, agg_pk, ids33[0], ids33, tweak_cache, NULL) == 1); - CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, agg_pk, ids33[1], ids33, tweak_cache, NULL) == 1); - CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, agg_pk, ids33[2], ids33, tweak_cache, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, ids33[0], ids33, tweak_cache, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, ids33[1], ids33, tweak_cache, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, ids33[2], ids33, tweak_cache, NULL) == 1); CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce[0], sr0, &session[0], tweak_cache) == 1); @@ -716,6 +710,7 @@ void frost_tweak_test(void) { unsigned char id[5][33]; const unsigned char *id_ptr[5]; const unsigned char *pok_ptr[5]; + const secp256k1_pubkey *pubshare_ptr[5]; /* Key Setup */ for (i = 0; i < 5; i++) { @@ -724,6 +719,7 @@ void frost_tweak_test(void) { vss_ptr[i] = vss_commitment[i]; id_ptr[i] = id[i]; pok_ptr[i] = pok[i]; + pubshare_ptr[i] = &pubshare[i]; CHECK(frost_create_pk(id[i], sk[i])); } @@ -734,14 +730,15 @@ void frost_tweak_test(void) { for (j = 0; j < 5; j++) { share_ptr[j] = &shares[j][i]; CHECK(secp256k1_frost_share_verify(CTX, 3, id_ptr[i], share_ptr[j], &vss_ptr[j]) == 1); - CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[j], 3, id_ptr[j], vss_ptr, 5) == 1); } - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &P_xonly[0], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); + CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[i], 3, id_ptr[i], vss_ptr, 5) == 1); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1); } - - frost_tweak_test_helper(&P_xonly[0], &agg_share[0], &agg_share[1], &agg_share[2], NULL, id_ptr, &pubshare[0], &pubshare[1], &pubshare[2]); - CHECK(secp256k1_frost_pubkey_get(CTX, &P[0], &P_xonly[0])); - CHECK(secp256k1_frost_pubkey_tweak(CTX, &tweak_cache, &P_xonly[0]) == 1); + /* Compute P0 and test signing for it */ + CHECK(secp256k1_frost_pubkey_gen(CTX, &tweak_cache, pubshare_ptr, 5, id_ptr) == 1); + CHECK(secp256k1_frost_pubkey_get(CTX, &P[0], &tweak_cache) == 1); + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &P_xonly[0], NULL, &P[0])); + frost_tweak_test_helper(&P_xonly[0], &agg_share[0], &agg_share[1], &agg_share[2], &tweak_cache, id_ptr, &pubshare[0], &pubshare[1], &pubshare[2]); /* Compute Pi = f(Pj) + tweaki*G where where j = i-1 and try signing for */ /* that key. If xonly is set to true, the function f is normalizes the input */ @@ -776,7 +773,7 @@ void frost_tweak_test(void) { } /* Performs a FROST DKG */ -void frost_dkg_test_helper(secp256k1_frost_share *agg_share, secp256k1_xonly_pubkey *agg_pk, const unsigned char * const* ids33) { +void frost_dkg_test_helper(secp256k1_frost_tweak_cache *tweak_cache, secp256k1_frost_share *agg_share, const unsigned char * const* ids33) { secp256k1_pubkey vss_commitment[5][3]; const secp256k1_pubkey *vss_ptr[5]; unsigned char pok[5][64]; @@ -785,11 +782,14 @@ void frost_dkg_test_helper(secp256k1_frost_share *agg_share, secp256k1_xonly_pub const secp256k1_frost_share *share_ptr[5]; int i, j; const unsigned char *pok_ptr[5]; + secp256k1_pubkey pubshare[5]; + const secp256k1_pubkey *pubshare_ptr[5]; for (i = 0; i < 5; i++) { secp256k1_testrand256(seed[i]); vss_ptr[i] = vss_commitment[i]; pok_ptr[i] = pok[i]; + pubshare_ptr[i] = &pubshare[i]; } for (i = 0; i < 5; i++) { CHECK(secp256k1_frost_shares_gen(CTX, shares[i], vss_commitment[i], pok[i], seed[i], 3, 5, ids33) == 1); @@ -798,12 +798,14 @@ void frost_dkg_test_helper(secp256k1_frost_share *agg_share, secp256k1_xonly_pub for (j = 0; j < 5; j++) { share_ptr[j] = &shares[j][i]; } - CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, ids33[i]) == 1); + CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[i], 3, ids33[i], vss_ptr, 5) == 1); + CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], share_ptr, vss_ptr, pok_ptr, 5, 3, ids33[i]) == 1); } + CHECK(secp256k1_frost_pubkey_gen(CTX, tweak_cache, pubshare_ptr, 5, ids33) == 1); } /* Signs a message with a FROST keypair */ -int frost_sign_test_helper(unsigned char *final_sig, const secp256k1_frost_share *agg_share, const secp256k1_xonly_pubkey *agg_pk, const unsigned char * const* ids33, const unsigned char *msg, const secp256k1_pubkey *adaptor) { +int frost_sign_test_helper(unsigned char *final_sig, const secp256k1_frost_share *agg_share, const unsigned char * const* ids33, const unsigned char *msg, const secp256k1_pubkey *adaptor, secp256k1_frost_tweak_cache *tweak_cache) { unsigned char session_id[3][32]; secp256k1_frost_secnonce secnonce[3]; secp256k1_frost_pubnonce pubnonce[3]; @@ -826,8 +828,8 @@ int frost_sign_test_helper(unsigned char *final_sig, const secp256k1_frost_share CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[i], &pubnonce[i], session_id[i], agg_share, NULL, NULL, NULL) == 1); } for (i = 0; i < 3; i++) { - CHECK(secp256k1_frost_nonce_process(CTX, &session, pubnonce_ptr, 3, msg, agg_pk, ids33[i], ids33, NULL, adaptor) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[i], &secnonce[i], &agg_share[i], &session, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session, pubnonce_ptr, 3, msg, ids33[i], ids33, tweak_cache, adaptor) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[i], &secnonce[i], &agg_share[i], &session, tweak_cache) == 1); } CHECK(secp256k1_frost_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 3) == 1); @@ -847,8 +849,9 @@ void frost_rand_scalar(secp256k1_scalar *scalar) { void frost_multi_hop_lock_tests(void) { secp256k1_frost_share agg_share_a[5]; secp256k1_frost_share agg_share_b[5]; - secp256k1_xonly_pubkey agg_pk_a; - secp256k1_xonly_pubkey agg_pk_b; + secp256k1_xonly_pubkey pk_a; + secp256k1_xonly_pubkey pk_b; + secp256k1_pubkey tmp; unsigned char sk_a[5][32]; unsigned char sk_b[5][32]; unsigned char asig_ab[64]; @@ -871,6 +874,8 @@ void frost_multi_hop_lock_tests(void) { const unsigned char *id_ptr_a[5]; unsigned char id_b[5][33]; const unsigned char *id_ptr_b[5]; + secp256k1_frost_tweak_cache cache_a; + secp256k1_frost_tweak_cache cache_b; /* Alice DKG */ for (i = 0; i < 5; i++) { @@ -879,7 +884,9 @@ void frost_multi_hop_lock_tests(void) { CHECK(frost_create_pk(id_a[i], sk_a[i])); } - frost_dkg_test_helper(agg_share_a, &agg_pk_a, id_ptr_a); + frost_dkg_test_helper(&cache_a, agg_share_a, id_ptr_a); + CHECK(secp256k1_frost_pubkey_get(CTX, &tmp, &cache_a) == 1); + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &pk_a, NULL, &tmp) == 1); /* Bob DKG */ for (i = 0; i < 5; i++) { @@ -888,7 +895,9 @@ void frost_multi_hop_lock_tests(void) { CHECK(frost_create_pk(id_b[i], sk_b[i])); } - frost_dkg_test_helper(agg_share_b, &agg_pk_b, id_ptr_b); + frost_dkg_test_helper(&cache_b, agg_share_b, id_ptr_b); + CHECK(secp256k1_frost_pubkey_get(CTX, &tmp, &cache_b) == 1); + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &pk_b, NULL, &tmp) == 1); /* Carol setup */ /* Proof of payment */ @@ -909,21 +918,21 @@ void frost_multi_hop_lock_tests(void) { CHECK(secp256k1_eckey_pubkey_tweak_add(&r_ge, &tp)); secp256k1_pubkey_save(&r, &r_ge); /* Encrypt Alice's signature with the left lock as the encryption key */ - nonce_parity_ab = frost_sign_test_helper(asig_ab, agg_share_a, &agg_pk_a, id_ptr_a, tx_ab, &l); + nonce_parity_ab = frost_sign_test_helper(asig_ab, agg_share_a, id_ptr_a, tx_ab, &l, &cache_a); /* Bob setup */ - CHECK(secp256k1_frost_verify_adaptor(CTX, asig_ab, tx_ab, &agg_pk_a, &l, nonce_parity_ab) == 1); + CHECK(secp256k1_frost_verify_adaptor(CTX, asig_ab, tx_ab, &pk_a, &l, nonce_parity_ab) == 1); secp256k1_testrand256(tx_bc); /* Encrypt Bob's signature with the right lock as the encryption key */ - nonce_parity_bc = frost_sign_test_helper(asig_bc, agg_share_b, &agg_pk_b, id_ptr_b, tx_bc, &r); + nonce_parity_bc = frost_sign_test_helper(asig_bc, agg_share_b, id_ptr_b, tx_bc, &r, &cache_b); /* Carol decrypt */ - CHECK(secp256k1_frost_verify_adaptor(CTX, asig_bc, tx_bc, &agg_pk_b, &r, nonce_parity_bc) == 1); + CHECK(secp256k1_frost_verify_adaptor(CTX, asig_bc, tx_bc, &pk_b, &r, nonce_parity_bc) == 1); secp256k1_scalar_set_b32(&deckey, pop, NULL); secp256k1_scalar_add(&deckey, &deckey, &tp); secp256k1_scalar_get_b32(buf, &deckey); CHECK(secp256k1_frost_adapt(CTX, sig_bc, asig_bc, buf, nonce_parity_bc)); - CHECK(secp256k1_schnorrsig_verify(CTX, sig_bc, tx_bc, sizeof(tx_bc), &agg_pk_b) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, sig_bc, tx_bc, sizeof(tx_bc), &pk_b) == 1); /* Bob recover and decrypt */ CHECK(secp256k1_frost_extract_adaptor(CTX, buf, sig_bc, asig_bc, nonce_parity_bc)); @@ -932,7 +941,7 @@ void frost_multi_hop_lock_tests(void) { secp256k1_scalar_add(&deckey, &deckey, &t2); secp256k1_scalar_get_b32(buf, &deckey); CHECK(secp256k1_frost_adapt(CTX, sig_ab, asig_ab, buf, nonce_parity_ab)); - CHECK(secp256k1_schnorrsig_verify(CTX, sig_ab, tx_ab, sizeof(tx_ab), &agg_pk_a) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, sig_ab, tx_ab, sizeof(tx_ab), &pk_a) == 1); /* Alice recover and derive proof of payment */ CHECK(secp256k1_frost_extract_adaptor(CTX, buf, sig_ab, asig_ab, nonce_parity_ab));