diff --git a/examples/frost.c b/examples/frost.c index 8a7e3b3bb..15a4b67ec 100644 --- a/examples/frost.c +++ b/examples/frost.c @@ -37,7 +37,6 @@ struct signer { secp256k1_frost_session session; secp256k1_frost_partial_sig partial_sig; secp256k1_pubkey vss_commitment[THRESHOLD]; - unsigned char vss_hash[32]; unsigned char pok[64]; unsigned char id[33]; }; @@ -70,7 +69,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 +100,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++) { @@ -125,15 +124,11 @@ int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_se /* Tweak the pubkey corresponding to the provided tweak cache, update the cache * and return the tweaked aggregate pk. */ -int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pk, secp256k1_frost_tweak_cache *cache) { +int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pk, secp256k1_frost_keygen_cache *cache) { secp256k1_pubkey output_pk; 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)) { @@ -164,7 +159,7 @@ int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pk, secp256k1_fr /* Sign a message hash with the given threshold and aggregate shares and store * the result in sig */ -int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const unsigned char* msg32, secp256k1_xonly_pubkey *pk, unsigned char *sig64, const secp256k1_frost_tweak_cache *cache) { +int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const unsigned char* msg32, unsigned char *sig64, const secp256k1_frost_keygen_cache *cache) { int i; int signer_id = 0; int signers[THRESHOLD]; @@ -183,7 +178,7 @@ int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, st } /* Initialize session and create secret nonce for signing and public * nonce to send to the other signers. */ - if (!secp256k1_frost_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_id, &signer_secrets[i].agg_share, msg32, pk, NULL)) { + if (!secp256k1_frost_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_id, &signer_secrets[i].agg_share, msg32, cache, NULL)) { return 0; } is_signer[i] = 0; /* Initialize is_signer */ @@ -212,7 +207,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 +246,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; + secp256k1_frost_keygen_cache keygen_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,23 +261,31 @@ 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, &keygen_cache, pubshares_ptr, N_SIGNERS, id_ptr)) { printf("FAILED\n"); return 1; } printf("ok\n"); printf("Tweaking................"); /* Optionally tweak the aggregate key */ - if (!tweak(ctx, &pk, &cache)) { + if (!tweak(ctx, &pk, &keygen_cache)) { printf("FAILED\n"); return 1; } printf("ok\n"); printf("Signing message........."); - if (!sign(ctx, signer_secrets, signers, msg, &pk, sig, &cache)) { + if (!sign(ctx, signer_secrets, signers, msg, sig, &keygen_cache)) { printf("FAILED\n"); return 1; } diff --git a/include/secp256k1_frost.h b/include/secp256k1_frost.h index 459cea029..9260ef189 100644 --- a/include/secp256k1_frost.h +++ b/include/secp256k1_frost.h @@ -43,7 +43,7 @@ extern "C" { */ typedef struct { unsigned char data[101]; -} secp256k1_frost_tweak_cache; +} secp256k1_frost_keygen_cache; /** Opaque data structure that holds a signer's _secret_ share. * @@ -219,7 +219,7 @@ SECP256K1_API int secp256k1_frost_shares_gen( const unsigned char *seed32, size_t threshold, size_t n_participants, - const unsigned char * const* ids33 + const unsigned char * const *ids33 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8); /** Aggregates shares @@ -239,10 +239,11 @@ SECP256K1_API int secp256k1_frost_shares_gen( * the resulting signature verifies). * Args: ctx: pointer to a context object * Out: agg_share: the aggregated share - * agg_pk: the aggregated x-only public key * In: shares: all key generation shares for the partcipant's index * vss_commitments: coefficient commitments of all participants ordered by - * the x-only pubkeys of the participants + * the IDs of the participants + * pok64s: proofs of knowledge for the shares ordered by the IDs of + * the participants * n_shares: the total number of shares * threshold: the minimum number of shares required to produce a * signature @@ -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,40 +306,46 @@ 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). +/** Computes a group public key and uses it to initialize a keygen_cache * * 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` + * Args: ctx: pointer to a context object + * Out: keygen_cache: pointer to a frost_keygen_cache struct that is required + * for signing (or observing the signing session and + * verifying partial signatures). + * In: pubshares: input array of pointers to the public verification + * shares of the participants ordered by the IDs of the + * participants + * n_pubshares: the total number of public verification shares + * ids33: array of the 33-byte participant IDs of the signers */ -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_keygen_cache *keygen_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 +/** Obtain the aggregate public key from a keygen_cache. + * + * This is only useful if you need the non-xonly public key, in particular for + * plain (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: 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` + * Out: pk: the FROST group public key. + * In: keygen_cache: pointer to a `frost_keygen_cache` struct initialized by + * `frost_pubkey_gen` */ -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_keygen_cache *keygen_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 +/** Apply ordinary "EC" tweaking to a public key in a given keygen_cache by * adding the generator multiplied with `tweak32` to it. This is useful for * deriving child keys from an aggregate public key via BIP32. * @@ -347,13 +353,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_tweak( * the following pseudocode buf and buf2 have identical contents (absent * earlier failures). * - * secp256k1_frost_share_agg(..., xonly_agg_pk, ...) - * secp256k1_frost_pubkey_tweak(..., tweak_cache, xonly_agg_pk) - * secp256k1_frost_pubkey_ec_tweak_add(..., output_pk, tweak_cache, tweak32) + * secp256k1_frost_pubkey_gen(..., keygen_cache, ...) + * secp256k1_frost_pubkey_tweak(..., keygen_cache, xonly_pk) + * secp256k1_frost_pubkey_ec_tweak_add(..., output_pk, keygen_cache, tweak32) * secp256k1_ec_pubkey_serialize(..., buf, output_pk) - * secp256k1_frost_pubkey_get(..., ec_agg_pk, xonly_agg_pk) - * secp256k1_ec_pubkey_tweak_add(..., ec_agg_pk, tweak32) - * secp256k1_ec_pubkey_serialize(..., buf2, ec_agg_pk) + * secp256k1_frost_pubkey_get(..., ec_pk, xonly_pk) + * secp256k1_ec_pubkey_tweak_add(..., ec_pk, tweak32) + * secp256k1_ec_pubkey_serialize(..., buf2, ec_pk) * * This function is required if you want to _sign_ for a tweaked aggregate key. * On the other hand, if you are only computing a public key, but not intending @@ -367,7 +373,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_tweak( * Out: output_pubkey: pointer to a public key to store the result. Will be set * to an invalid value if this function returns 0. If you * do not need it, this arg can be NULL. - * In/Out: tweak_cache: pointer to a `frost_tweak_cache` struct initialized by + * In/Out: keygen_cache: pointer to a `frost_keygen_cache` struct initialized by * `frost_pubkey_tweak` * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid * according to `secp256k1_ec_seckey_verify`, this function @@ -378,11 +384,11 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_tweak( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_ec_tweak_add( const secp256k1_context *ctx, secp256k1_pubkey *output_pubkey, - secp256k1_frost_tweak_cache *tweak_cache, + secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -/** Apply x-only tweaking to a public key in a given tweak_cache by adding the +/** Apply x-only tweaking to a public key in a given keygen_cache by adding the * generator multiplied with `tweak32` to it. This is useful for creating * Taproot outputs. * @@ -391,8 +397,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_ec_tweak_a * failures) returns 1. * * secp256k1_frost_share_agg(..., agg_pk, ...) - * secp256k1_frost_pubkey_tweak(..., tweak_cache, agg_pk) - * secp256k1_frost_pubkey_xonly_tweak_add(..., output_pk, tweak_cache, tweak32) + * secp256k1_frost_pubkey_tweak(..., keygen_cache, agg_pk) + * secp256k1_frost_pubkey_xonly_tweak_add(..., output_pk, keygen_cache, tweak32) * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) * @@ -408,7 +414,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_ec_tweak_a * Out: output_pubkey: pointer to a public key to store the result. Will be set * to an invalid value if this function returns 0. If you * do not need it, this arg can be NULL. - * In/Out: tweak_cache: pointer to a `frost_tweak_cache` struct initialized by + * In/Out: keygen_cache: pointer to a `frost_keygen_cache` struct initialized by * `frost_pubkey_tweak` * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid * according to secp256k1_ec_seckey_verify, this function @@ -419,7 +425,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_ec_tweak_a SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_xonly_tweak_add( const secp256k1_context *ctx, secp256k1_pubkey *output_pubkey, - secp256k1_frost_tweak_cache *tweak_cache, + secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -461,7 +467,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_xonly_twea * signing, if already known (can be NULL) * msg32: the 32-byte message that will later be signed, if * already known (can be NULL) - * agg_pk: the FROST-aggregated public key (can be NULL) + * keygen_cache: pointer to the keygen_cache that was used to create the group + * (and potentially tweaked) public key if already known + * (can be NULL) * extra_input32: an optional 32-byte array that is input to the nonce * derivation function (can be NULL) */ @@ -472,7 +480,7 @@ SECP256K1_API int secp256k1_frost_nonce_gen( const unsigned char *session_id32, const secp256k1_frost_share *agg_share, const unsigned char *msg32, - const secp256k1_xonly_pubkey *agg_pk, + const secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *extra_input32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -490,11 +498,10 @@ 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) + * keygen_cache: pointer to frost_keygen_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) @@ -505,10 +512,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_nonce_process( 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, + const unsigned char * const *ids33, + const secp256k1_frost_keygen_cache *keygen_cache, const secp256k1_pubkey *adaptor ) 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(8); @@ -529,7 +535,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) + * keygen_cache: pointer to frost_keygen_cache struct */ SECP256K1_API int secp256k1_frost_partial_sign( const secp256k1_context *ctx, @@ -537,15 +543,15 @@ SECP256K1_API int secp256k1_frost_partial_sign( secp256k1_frost_secnonce *secnonce, 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); + const secp256k1_frost_keygen_cache *keygen_cache +) 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 * * The signature is verified for a specific signing session. In order to avoid * accidentally verifying a signature from a different or non-existing signing * session, you must ensure the following: - * 1. The `tweak_cache` argument is identical to the one used to create the + * 1. The `keygen_cache` argument is identical to the one used to create the * `session` with `frost_nonce_process`. * 2. The `pubshare` argument must be the output of * `secp256k1_frost_compute_pubshare` for the signer's ID. @@ -565,7 +571,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) + * keygen_cache: pointer to frost_keygen_cache struct */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_verify( const secp256k1_context *ctx, @@ -573,8 +579,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_verif const secp256k1_frost_pubnonce *pubnonce, 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); + const secp256k1_frost_keygen_cache *keygen_cache +) 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/ctime_tests.c b/src/ctime_tests.c index 44071b4d3..06848ea7e 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -357,13 +357,12 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { #ifdef ENABLE_MODULE_FROST { secp256k1_pubkey pk[2]; - secp256k1_xonly_pubkey agg_pk; unsigned char session_id[32]; unsigned char seed[2][32]; secp256k1_frost_secnonce secnonce[2]; secp256k1_frost_pubnonce pubnonce[2]; const secp256k1_frost_pubnonce *pubnonce_ptr[2]; - secp256k1_frost_tweak_cache cache; + secp256k1_frost_keygen_cache cache; secp256k1_frost_session session; secp256k1_frost_partial_sig partial_sig; const secp256k1_frost_partial_sig *partial_sig_ptr[1]; @@ -384,6 +383,8 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { const unsigned char *id_ptr[2]; size_t size = 33; const unsigned char *pok_ptr[2]; + secp256k1_pubkey pubshare[2]; + const secp256k1_pubkey *pubshares_ptr[2]; id_ptr[0] = id[0]; id_ptr[1] = id[1]; @@ -409,6 +410,8 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { vss_ptr[1] = vss_commitment[1]; pok_ptr[0] = pok[0]; pok_ptr[1] = pok[1]; + pubshares_ptr[0] = &pubshare[0]; + pubshares_ptr[1] = &pubshare[1]; CHECK(secp256k1_keypair_create(ctx, &keypair, key)); CHECK(secp256k1_keypair_create(ctx, &keypair2, key2)); @@ -435,23 +438,25 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { SECP256K1_CHECKMEM_DEFINE(&vss_commitment[1][1], sizeof(secp256k1_pubkey)); SECP256K1_CHECKMEM_DEFINE(pok[0], 64); SECP256K1_CHECKMEM_DEFINE(pok[1], 64); - ret = secp256k1_frost_share_agg(ctx, &agg_share, &agg_pk, share_ptr, vss_ptr, pok_ptr, 2, 2, id_ptr[0]); + ret = secp256k1_frost_share_agg(ctx, &agg_share, share_ptr, vss_ptr, pok_ptr, 2, 2, id_ptr[0]); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); + CHECK(secp256k1_frost_compute_pubshare(ctx, pubshares_ptr[0], 2, id_ptr[0], vss_ptr, 2)); + CHECK(secp256k1_frost_compute_pubshare(ctx, pubshares_ptr[1], 2, id_ptr[1], vss_ptr, 2)); + CHECK(secp256k1_frost_pubkey_gen(ctx, &cache, pubshares_ptr, 2, id_ptr)); /* nonce_gen */ SECP256K1_CHECKMEM_UNDEFINE(session_id, sizeof(session_id)); CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor)); SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input)); SECP256K1_CHECKMEM_UNDEFINE(sec_adaptor, sizeof(sec_adaptor)); - CHECK(secp256k1_frost_pubkey_tweak(ctx, &cache, &agg_pk) == 1); - ret = secp256k1_frost_nonce_gen(ctx, &secnonce[0], &pubnonce[0], session_id, &agg_share, msg, &agg_pk, extra_input); + ret = secp256k1_frost_nonce_gen(ctx, &secnonce[0], &pubnonce[0], session_id, &agg_share, msg, &cache, extra_input); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); - ret = secp256k1_frost_nonce_gen(ctx, &secnonce[1], &pubnonce[1], session_id, &agg_share, msg, &agg_pk, extra_input); + ret = secp256k1_frost_nonce_gen(ctx, &secnonce[1], &pubnonce[1], session_id, &agg_share, msg, &cache, extra_input); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); /* partial_sign */ - CHECK(secp256k1_frost_nonce_process(ctx, &session, pubnonce_ptr, 2, msg, &agg_pk, id_ptr[0], id_ptr, &cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(ctx, &session, pubnonce_ptr, 2, msg, id_ptr[0], id_ptr, &cache, &adaptor) == 1); ret = secp256k1_keypair_create(ctx, &keypair, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); diff --git a/src/modules/frost/frost.md b/src/modules/frost/frost.md index c9bfa1347..36b146c7b 100644 --- a/src/modules/frost/frost.md +++ b/src/modules/frost/frost.md @@ -32,27 +32,31 @@ Users of the frost module must take great care to make sure of the following: # Key Generation -1. Generate a keypair with `secp256k1_keypair_create` and obtain the x-only - public key with `secp256k1_keypair_xonly_pub`, and distribute it to each - other participant to be used as an authentication key and identifier. +1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key + with `secp256k1_keypair_pub`, and distribute it to each other participant to + be used as an authentication key and identifier. 2. Generate a VSS commitment, proof-of-knowledge, and shares with `secp256k1_frost_shares_gen`. The VSS commitment and proof-of-knowledge must be broadcast to all participants. Assign each participant a share according to the order of `ids33` and distribute the shares to the participants using a secure channel. 3. After receiving a share and commitment set from each participant, call - `secp256k1_frost_share_agg` to compute the aggregate share, group public - key, and VSS hash. If this function returns an error, - `secp256k1_frost_share_verify` is called on each share to determine which - participants submitted faulty shares. -4. Optionally compute the public verification share by calling - `secp256k1_frost_compute_pubshare` with the x-only public key of each - participant. This share is required by `secp256k1_frost_partial_sig_verify` - to verify partial signatures generated by `secp256k1_frost_partial_sign`. + `secp256k1_frost_share_agg` to compute the aggregate share. If this function + returns an error, `secp256k1_frost_share_verify` is called on each share to + determine which participants submitted faulty shares. +4. Compute the public verification shares for each participant by calling + `secp256k1_frost_compute_pubshare` with the public key of the participant. + This share is required by `secp256k1_frost_partial_sig_verify` to verify + partial signatures generated by `secp256k1_frost_partial_sign`, and public + shares are required by `secp256k1_frost_pubkey_gen` to generate the group + public key. +5. Generate the group key by passing the public shares of all participants to + `secp256k1_frost_pubkey_gen`, which will initialize a key generation + context. The context can be passed to `secp256k1_frost_pubkey_get` to obtain + the group public key. # Tweaking - A (Taproot) tweak can be added to the resulting public key with `secp256k1_xonly_pubkey_tweak_add`, after converting it to an xonly pubkey if necessary with `secp256k1_xonly_pubkey_from_pubkey`. @@ -65,16 +69,17 @@ Tweaks can also be chained together by tweaking an already tweaked key. # Signing -1. Optionally add a tweak by calling `secp256k1_frost_pubkey_tweak` and then +1. Initialize the key generation context with `secp256k1_frost_pubkey_gen`. +2. Optionally add a tweak by calling `secp256k1_frost_pubkey_tweak` and then `secp256k1_frost_pubkey_xonly_tweak_add` for a Taproot tweak and `secp256k1_frost_pubkey_ec_tweak_add` for an ordinary tweak. -2. Generate a pair of secret and public nonce with `secp256k1_frost_nonce_gen` +3. Generate a pair of secret and public nonce with `secp256k1_frost_nonce_gen` and send the public nonce to the other signers. -3. Process the aggregate nonce with `secp256k1_frost_nonce_process`. -4. Create a partial signature with `secp256k1_frost_partial_sign`. -5. Verify the partial signatures (optional in some scenarios) with +4. Process the aggregate nonce with `secp256k1_frost_nonce_process`. +5. Create a partial signature with `secp256k1_frost_partial_sign`. +6. Verify the partial signatures (optional in some scenarios) with `secp256k1_frost_partial_sig_verify`. -6. Someone (not necessarily the signer) obtains all partial signatures and +7. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_frost_partial_sig_agg`. @@ -86,10 +91,10 @@ viewed as a pre-processing step that is run whenever convenient to the signers. This disables some of the defense-in-depth measures that may protect against API misuse in some cases. Similarly, the API supports an alternative protocol flow where generating the key (see Key Generation above) is allowed to happen -after exchanging nonces (step 2). +after exchanging nonces (step 3). # Verification A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips -steps 2 and 4. +steps 3 and 5. diff --git a/src/modules/frost/keygen.h b/src/modules/frost/keygen.h index fb17f3c67..60f494973 100644 --- a/src/modules/frost/keygen.h +++ b/src/modules/frost/keygen.h @@ -15,14 +15,19 @@ 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; +} secp256k1_keygen_cache_internal; -static int secp256k1_tweak_cache_load(const secp256k1_context* ctx, secp256k1_tweak_cache_internal *cache_i, const secp256k1_frost_tweak_cache *cache); +static int secp256k1_keygen_cache_load(const secp256k1_context* ctx, secp256k1_keygen_cache_internal *cache_i, const secp256k1_frost_keygen_cache *cache); static int secp256k1_frost_share_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_frost_share* share); 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..b152bca1e 100644 --- a/src/modules/frost/keygen_impl.h +++ b/src/modules/frost/keygen_impl.h @@ -20,7 +20,7 @@ #include "../../hash.h" #include "../../scalar.h" -static const unsigned char secp256k1_frost_tweak_cache_magic[4] = { 0x40, 0x25, 0x2e, 0x41 }; +static const unsigned char secp256k1_frost_keygen_cache_magic[4] = { 0x40, 0x25, 0x2e, 0x41 }; /* A tweak cache consists of * - 4 byte magic set during initialization to allow detecting an uninitialized @@ -30,22 +30,22 @@ static const unsigned char secp256k1_frost_tweak_cache_magic[4] = { 0x40, 0x25, * - 32 byte tweak */ /* Requires that cache_i->pk is not infinity. */ -static void secp256k1_tweak_cache_save(secp256k1_frost_tweak_cache *cache, secp256k1_tweak_cache_internal *cache_i) { +static void secp256k1_keygen_cache_save(secp256k1_frost_keygen_cache *cache, secp256k1_keygen_cache_internal *cache_i) { unsigned char *ptr = cache->data; - memcpy(ptr, secp256k1_frost_tweak_cache_magic, 4); + memcpy(ptr, secp256k1_frost_keygen_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; secp256k1_scalar_get_b32(ptr, &cache_i->tweak); } -static int secp256k1_tweak_cache_load(const secp256k1_context* ctx, secp256k1_tweak_cache_internal *cache_i, const secp256k1_frost_tweak_cache *cache) { +static int secp256k1_keygen_cache_load(const secp256k1_context* ctx, secp256k1_keygen_cache_internal *cache_i, const secp256k1_frost_keygen_cache *cache) { const unsigned char *ptr = cache->data; - ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_frost_tweak_cache_magic, 4) == 0); + ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_frost_keygen_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,12 +275,21 @@ static int secp256k1_frost_compute_pubshare_ecmult_callback(secp256k1_scalar *sc return 1; } -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; +static int secp256k1_frost_interpolate_pubkey_ecmult_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; + } - secp256k1_scalar_set_int(sc, 1); - /* the public key is the first index of each set of coefficients */ - return secp256k1_pubkey_load(ctx->ctx, pt, &ctx->pks[idx][0]); + *sc = l; + + return 1; } /* See draft-irtf-cfrg-frost-08#appendix-C.2 */ @@ -326,9 +342,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 +379,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 +394,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,67 +430,54 @@ 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 *agg_pk, const secp256k1_frost_keygen_cache *keyagg_cache) { + secp256k1_keygen_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); - /* 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_keygen_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) { - secp256k1_tweak_cache_internal cache_i = { 0 }; +int secp256k1_frost_pubkey_gen(const secp256k1_context* ctx, secp256k1_frost_keygen_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_keygen_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); + + 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; - /* 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)) { + /* TODO: add scratch */ + if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_frost_interpolate_pubkey_ecmult_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_keygen_cache_save(cache, &cache_i); return 1; } -static int secp256k1_frost_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_tweak_cache *tweak_cache, const unsigned char *tweak32, int xonly) { - secp256k1_tweak_cache_internal cache_i; +static int secp256k1_frost_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *tweak32, int xonly) { + secp256k1_keygen_cache_internal cache_i; int overflow = 0; secp256k1_scalar tweak; @@ -505,10 +485,10 @@ static int secp256k1_frost_pubkey_tweak_add_internal(const secp256k1_context* ct if (output_pubkey != NULL) { memset(output_pubkey, 0, sizeof(*output_pubkey)); } - ARG_CHECK(tweak_cache != NULL); + ARG_CHECK(keygen_cache != NULL); ARG_CHECK(tweak32 != NULL); - if (!secp256k1_tweak_cache_load(ctx, &cache_i, tweak_cache)) { + if (!secp256k1_keygen_cache_load(ctx, &cache_i, keygen_cache)) { return 0; } secp256k1_scalar_set_b32(&tweak, tweak32, &overflow); @@ -525,19 +505,52 @@ static int secp256k1_frost_pubkey_tweak_add_internal(const secp256k1_context* ct } /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */ VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk)); - secp256k1_tweak_cache_save(tweak_cache, &cache_i); + secp256k1_keygen_cache_save(keygen_cache, &cache_i); if (output_pubkey != NULL) { secp256k1_pubkey_save(output_pubkey, &cache_i.pk); } return 1; } -int secp256k1_frost_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_tweak_cache *tweak_cache, const unsigned char *tweak32) { - return secp256k1_frost_pubkey_tweak_add_internal(ctx, output_pubkey, tweak_cache, tweak32, 0); +int secp256k1_frost_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *tweak32) { + return secp256k1_frost_pubkey_tweak_add_internal(ctx, output_pubkey, keygen_cache, tweak32, 0); } -int secp256k1_frost_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_tweak_cache *tweak_cache, const unsigned char *tweak32) { - return secp256k1_frost_pubkey_tweak_add_internal(ctx, output_pubkey, tweak_cache, tweak32, 1); +int secp256k1_frost_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *tweak32) { + return secp256k1_frost_pubkey_tweak_add_internal(ctx, output_pubkey, keygen_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..bbc3cd73e 100644 --- a/src/modules/frost/session_impl.h +++ b/src/modules/frost/session_impl.h @@ -243,7 +243,8 @@ static void secp256k1_nonce_function_frost(secp256k1_scalar *k, const unsigned c } } -int secp256k1_frost_nonce_gen(const secp256k1_context* ctx, secp256k1_frost_secnonce *secnonce, secp256k1_frost_pubnonce *pubnonce, const unsigned char *session_id32, const secp256k1_frost_share *share, const unsigned char *msg32, const secp256k1_xonly_pubkey *pk, const unsigned char *extra_input32) { +int secp256k1_frost_nonce_gen(const secp256k1_context* ctx, secp256k1_frost_secnonce *secnonce, secp256k1_frost_pubnonce *pubnonce, const unsigned char *session_id32, const secp256k1_frost_share *share, const unsigned char *msg32, const secp256k1_frost_keygen_cache *keygen_cache, const unsigned char *extra_input32) { + secp256k1_keygen_cache_internal cache_i; secp256k1_scalar k[2]; secp256k1_ge nonce_pt[2]; int i; @@ -272,8 +273,8 @@ int secp256k1_frost_nonce_gen(const secp256k1_context* ctx, secp256k1_frost_secn memset(&acc, 0, sizeof(acc)); } + /* Check that the share is valid to be able to sign for it later. */ if (share != NULL) { - /* Check that the share is valid to be able to sign for it later. */ secp256k1_scalar sk; ret &= secp256k1_frost_share_load(ctx, &sk, share); @@ -288,12 +289,15 @@ int secp256k1_frost_nonce_gen(const secp256k1_context* ctx, secp256k1_frost_secn #endif } - if (pk != NULL) { - if (!secp256k1_xonly_pubkey_serialize(ctx, pk_ser, pk)) { + if (keygen_cache != NULL) { + if (!secp256k1_keygen_cache_load(ctx, &cache_i, keygen_cache)) { return 0; } + /* The loaded point cache_i.pk can not be the point at infinity. */ + secp256k1_fe_get_b32(pk_ser, &cache_i.pk.x); pk_ser_ptr = pk_ser; } + secp256k1_nonce_function_frost(k, session_id32, msg32, sk_ser_ptr, pk_ser_ptr, extra_input32); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); @@ -373,62 +377,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_keygen_cache *keygen_cache, const secp256k1_pubkey *adaptor) { + secp256k1_keygen_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 +406,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(keygen_cache != NULL); ARG_CHECK(n_pubnonces > 1); - if (!secp256k1_xonly_pubkey_serialize(ctx, pk32, pk)) { + if (!secp256k1_keygen_cache_load(ctx, &cache_i, keygen_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 +433,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. */ @@ -515,10 +458,11 @@ void secp256k1_frost_partial_sign_clear(secp256k1_scalar *sk, secp256k1_scalar * secp256k1_scalar_clear(&k[1]); } -int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_partial_sig *partial_sig, secp256k1_frost_secnonce *secnonce, const secp256k1_frost_share *share, const secp256k1_frost_session *session, const secp256k1_frost_tweak_cache *tweak_cache) { +int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_partial_sig *partial_sig, secp256k1_frost_secnonce *secnonce, const secp256k1_frost_share *share, const secp256k1_frost_session *session, const secp256k1_frost_keygen_cache *keygen_cache) { secp256k1_scalar sk; secp256k1_scalar k[2]; secp256k1_scalar s; + secp256k1_keygen_cache_internal cache_i; secp256k1_frost_session_internal session_i; int ret; @@ -537,26 +481,29 @@ int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_p ARG_CHECK(partial_sig != NULL); ARG_CHECK(share != NULL); + ARG_CHECK(keygen_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_keygen_cache_load(ctx, &cache_i, keygen_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) { @@ -574,7 +521,8 @@ int secp256k1_frost_partial_sign(const secp256k1_context* ctx, secp256k1_frost_p return 1; } -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) { +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_keygen_cache *keygen_cache) { + secp256k1_keygen_cache_internal cache_i; secp256k1_frost_session_internal session_i; secp256k1_scalar e, s; secp256k1_gej pkj; @@ -587,6 +535,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(keygen_cache != NULL); ARG_CHECK(session != NULL); if (!secp256k1_frost_session_load(ctx, &session_i, session)) { @@ -605,23 +554,25 @@ int secp256k1_frost_partial_sig_verify(const secp256k1_context* ctx, const secp2 if (!secp256k1_pubkey_load(ctx, &pkp, pubshare)) { return 0; } + if (!secp256k1_keygen_cache_load(ctx, &cache_i, keygen_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..ab33617aa 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_keygen_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,10 +159,10 @@ 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_frost_tweak_cache tweak_cache; - secp256k1_frost_tweak_cache invalid_tweak_cache; + secp256k1_pubkey pk; + secp256k1_xonly_pubkey pk_xonly; + secp256k1_frost_keygen_cache keygen_cache; + secp256k1_frost_keygen_cache invalid_keygen_cache; secp256k1_frost_session session[5]; secp256k1_frost_session invalid_session; secp256k1_xonly_pubkey invalid_pk; @@ -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)); @@ -193,7 +201,7 @@ void frost_api_tests(void) { memset(&invalid_partial_sig, 0, sizeof(invalid_partial_sig)); memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce)); memset(&invalid_vss_pk, 0, sizeof(invalid_vss_pk)); - memset(&invalid_tweak_cache, 0, sizeof(invalid_tweak_cache)); + memset(&invalid_keygen_cache, 0, sizeof(invalid_keygen_cache)); memset(&invalid_session, 0, sizeof(invalid_session)); frost_pubnonce_summing_to_inf(inf_pubnonce); @@ -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,75 +337,75 @@ 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, &keygen_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, &keygen_cache, NULL, 5, id_ptr)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, &keygen_cache, pubshare_ptr, 0, id_ptr)); + CHECK_ILLEGAL(CTX, secp256k1_frost_pubkey_gen(CTX, &keygen_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, &keygen_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, &keygen_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); + int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_frost_keygen_cache *keygen_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; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_tweak_cache, tweak) == 1); - /* Reset tweak_cache */ - tmp_tweak_cache = tweak_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_tweak_cache, tweak) == 1); - tmp_tweak_cache = tweak_cache; - CHECK((*tweak_func[i])(CTX, NULL, &tmp_tweak_cache, tweak) == 1); - tmp_tweak_cache = tweak_cache; + secp256k1_frost_keygen_cache tmp_keygen_cache = keygen_cache; + CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keygen_cache, tweak) == 1); + /* Reset keygen_cache */ + tmp_keygen_cache = keygen_cache; + CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keygen_cache, tweak) == 1); + tmp_keygen_cache = keygen_cache; + CHECK((*tweak_func[i])(CTX, NULL, &tmp_keygen_cache, tweak) == 1); + tmp_keygen_cache = keygen_cache; CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, NULL, tweak)); CHECK(frost_memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); - tmp_tweak_cache = tweak_cache; - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &tmp_tweak_cache, NULL)); + tmp_keygen_cache = keygen_cache; + CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keygen_cache, NULL)); CHECK(frost_memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); - tmp_tweak_cache = tweak_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_tweak_cache, max64) == 0); + tmp_keygen_cache = keygen_cache; + CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keygen_cache, max64) == 0); CHECK(frost_memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); - tmp_tweak_cache = tweak_cache; - /* Uninitialized tweak_cache */ - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &invalid_tweak_cache, tweak)); + tmp_keygen_cache = keygen_cache; + /* Uninitialized keygen_cache */ + CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &invalid_keygen_cache, tweak)); CHECK(frost_memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0); } } /** 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, &keygen_cache, max64) == 1); + CHECK_ILLEGAL(STATIC_CTX, secp256k1_frost_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &keygen_cache, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, NULL, &pubnonce[0], session_id[0], &agg_share[0], msg, &keygen_cache, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], NULL, session_id[0], &agg_share[0], msg, &keygen_cache, max64)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, &agg_share[0], msg, &keygen_cache, 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, &keygen_cache, 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, &keygen_cache, max64) == 1); + CHECK(secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, msg, &keygen_cache, 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, &keygen_cache, 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, &keygen_cache, 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_ILLEGAL(CTX, secp256k1_frost_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], &agg_share[0], msg, &invalid_keygen_cache, 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, &keygen_cache, 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,50 +435,49 @@ 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, &keygen_cache, &adaptor) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, NULL, pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], NULL, 3, msg, id_ptr[0], id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 0, msg, id_ptr[0], id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], invalid_pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, NULL, id_ptr[0], id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, NULL, id_ptr, &keygen_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], NULL, &keygen_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_keygen_cache, &adaptor)); + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &keygen_cache, NULL) == 1); + CHECK_ILLEGAL(CTX, secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &keygen_cache, (secp256k1_pubkey *)&invalid_pk)); + + CHECK(secp256k1_frost_nonce_process(CTX, &session[0], pubnonce_ptr, 3, msg, id_ptr[0], id_ptr, &keygen_cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, id_ptr[1], id_ptr, &keygen_cache, &adaptor) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, id_ptr[2], id_ptr, &keygen_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); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &keygen_cache) == 1); /* The secnonce is set to 0 and subsequent signing attempts fail */ CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros68, sizeof(secnonce_tmp)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &keygen_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, NULL, &secnonce_tmp, &agg_share[0], &session[0], &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, NULL, &secnonce_tmp, &agg_share[0], &session[0], &keygen_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], NULL, &agg_share[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &agg_share[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &session[0], &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], NULL, &agg_share[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &agg_share[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &session[0], &keygen_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &invalid_share, &session[0], &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &invalid_share, &session[0], &keygen_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], NULL, &tweak_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], NULL, &keygen_cache)); 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)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &invalid_session, &keygen_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)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &agg_share[0], &session[0], &invalid_keygen_cache)); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce[0], &agg_share[0], &session[0], &tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[1], &secnonce[1], &agg_share[1], &session[1], &tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[2], &secnonce[2], &agg_share[2], &session[2], &tweak_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce[0], &agg_share[0], &session[0], &keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[1], &secnonce[1], &agg_share[1], &session[1], &keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[2], &secnonce[2], &agg_share[2], &session[2], &keygen_cache) == 1); CHECK(secp256k1_frost_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_serialize(CTX, NULL, &partial_sig[0])); @@ -502,22 +496,22 @@ void frost_api_tests(void) { } /** Partial signature verification */ - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pubshare[0], &session[0], &tweak_cache) == 0); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, NULL, &pubnonce[0], &pubshare[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pubshare[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], NULL, &pubshare[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pubshare[0], &session[0], &tweak_cache)); - CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &session[0], &tweak_cache)); - 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], &invalid_tweak_cache)); - - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pubshare[1], &session[1], &tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[2], &pubnonce[2], &pubshare[2], &session[2], &tweak_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pubshare[0], &session[0], &keygen_cache) == 0); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, NULL, &pubnonce[0], &pubshare[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pubshare[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], NULL, &pubshare[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pubshare[0], &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_vss_pk, &session[0], &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], NULL, &keygen_cache)); + CHECK_ILLEGAL(CTX, secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &invalid_session, &keygen_cache)); + 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_keygen_cache)); + + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pubshare[0], &session[0], &keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pubshare[1], &session[1], &keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[2], &pubnonce[2], &pubshare[2], &session[2], &keygen_cache) == 1); /** Signature aggregation and verification */ CHECK(secp256k1_frost_partial_sig_agg(CTX, pre_sig, &session[0], partial_sig_ptr, 3) == 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); @@ -653,8 +647,8 @@ void frost_sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char } /* Attempts to create a signature for the aggregate public key using given secret - * keys and tweak_cache. */ -void frost_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const secp256k1_frost_share *sr0, const secp256k1_frost_share *sr1, const secp256k1_frost_share *sr2, secp256k1_frost_tweak_cache *tweak_cache, const unsigned char * const* ids33, const secp256k1_pubkey *sr_pk0, const secp256k1_pubkey *sr_pk1, const secp256k1_pubkey *sr_pk2) { + * keys and keygen_cache. */ +void frost_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const secp256k1_frost_share *sr0, const secp256k1_frost_share *sr1, const secp256k1_frost_share *sr2, secp256k1_frost_keygen_cache *keygen_cache, const unsigned char * const* ids33, const secp256k1_pubkey *sr_pk0, const secp256k1_pubkey *sr_pk1, const secp256k1_pubkey *sr_pk2) { unsigned char session_id[3][32]; unsigned char msg[32]; secp256k1_frost_secnonce secnonce[3]; @@ -679,18 +673,18 @@ 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, keygen_cache, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[1], pubnonce_ptr, 3, msg, ids33[1], ids33, keygen_cache, NULL) == 1); + CHECK(secp256k1_frost_nonce_process(CTX, &session[2], pubnonce_ptr, 3, msg, ids33[2], ids33, keygen_cache, NULL) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce[0], sr0, &session[0], tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[1], &secnonce[1], sr1, &session[1], tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[2], &secnonce[2], sr2, &session[2], tweak_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[0], &secnonce[0], sr0, &session[0], keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[1], &secnonce[1], sr1, &session[1], keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[2], &secnonce[2], sr2, &session[2], keygen_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], sr_pk0, &session[0], tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], sr_pk1, &session[1], tweak_cache) == 1); - CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[2], &pubnonce[2], sr_pk2, &session[2], tweak_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], sr_pk0, &session[0], keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], sr_pk1, &session[1], keygen_cache) == 1); + CHECK(secp256k1_frost_partial_sig_verify(CTX, &partial_sig[2], &pubnonce[2], sr_pk2, &session[2], keygen_cache) == 1); CHECK(secp256k1_frost_partial_sig_agg(CTX, final_sig, &session[0], partial_sig_ptr, 3) == 1); CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), agg_pk) == 1); @@ -701,7 +695,7 @@ void frost_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const secp256 void frost_tweak_test(void) { unsigned char sk[5][32]; secp256k1_pubkey pubshare[5]; - secp256k1_frost_tweak_cache tweak_cache; + secp256k1_frost_keygen_cache keygen_cache; enum { N_TWEAKS = 8 }; secp256k1_pubkey P[N_TWEAKS + 1]; secp256k1_xonly_pubkey P_xonly[N_TWEAKS + 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, &keygen_cache, pubshare_ptr, 5, id_ptr) == 1); + CHECK(secp256k1_frost_pubkey_get(CTX, &P[0], &keygen_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], &keygen_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 */ @@ -754,9 +751,9 @@ void frost_tweak_test(void) { secp256k1_testrand256(tweak); if (xonly) { - CHECK(secp256k1_frost_pubkey_xonly_tweak_add(CTX, &P[i], &tweak_cache, tweak) == 1); + CHECK(secp256k1_frost_pubkey_xonly_tweak_add(CTX, &P[i], &keygen_cache, tweak) == 1); } else { - CHECK(secp256k1_frost_pubkey_ec_tweak_add(CTX, &P[i], &tweak_cache, tweak) == 1); + CHECK(secp256k1_frost_pubkey_ec_tweak_add(CTX, &P[i], &keygen_cache, tweak) == 1); } CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &P_xonly[i], &P_parity, &P[i])); /* Check that frost_pubkey_tweak_add produces same result as */ @@ -771,12 +768,12 @@ void frost_tweak_test(void) { CHECK(secp256k1_memcmp_var(&tmp_key, &P[i], sizeof(tmp_key)) == 0); } /* Test signing for P[i] */ - frost_tweak_test_helper(&P_xonly[i], &agg_share[0], &agg_share[1], &agg_share[2], &tweak_cache, id_ptr, &pubshare[0], &pubshare[1], &pubshare[2]); + frost_tweak_test_helper(&P_xonly[i], &agg_share[0], &agg_share[1], &agg_share[2], &keygen_cache, id_ptr, &pubshare[0], &pubshare[1], &pubshare[2]); } } /* 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_keygen_cache *keygen_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, keygen_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_keygen_cache *keygen_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, keygen_cache, adaptor) == 1); + CHECK(secp256k1_frost_partial_sign(CTX, &partial_sig[i], &secnonce[i], &agg_share[i], &session, keygen_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_keygen_cache cache_a; + secp256k1_frost_keygen_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));