diff --git a/src/modules/frost/tests_impl.h b/src/modules/frost/tests_impl.h index e02904be8..b1153062e 100644 --- a/src/modules/frost/tests_impl.h +++ b/src/modules/frost/tests_impl.h @@ -4,84 +4,139 @@ #include "include/secp256k1_frost.h" #include <secp256k1_musig.h> + /* Number of public keys involved in creating the aggregate signature */ +#define N_SIGNERS 3 + + /* Threshold required in creating the aggregate signature */ +#define THRESHOLD 2 + void run_frost_tests(void) { - unsigned char sk1[32]; - unsigned char sk2[32]; - unsigned char sk3[32]; - unsigned char pk1[32]; - unsigned char pk2[32]; - size_t participants[2]; - secp256k1_scalar coefficients1[2]; - secp256k1_scalar coefficients2[2]; - secp256k1_scalar coefficients3[2]; - secp256k1_xonly_pubkey commitments1[2]; - secp256k1_xonly_pubkey commitments2[2]; - secp256k1_xonly_pubkey commitments3[2]; - secp256k1_frost_share shares1[3]; - secp256k1_frost_share shares2[3]; - secp256k1_frost_share shares3[3]; - secp256k1_frost_share agg1, agg2, agg3; - secp256k1_frost_share share_buf[3]; - secp256k1_xonly_pubkey key_buf[3]; - secp256k1_scalar l1, l2; + /* TODO: c.f. musig, example.c */ + unsigned char pk1[33]; + unsigned char pk2[33]; + unsigned char sig[64]; + unsigned char msg[32]; + unsigned char id[32]; + unsigned char sk[32]; + unsigned char p_sigs[THRESHOLD][32]; + size_t participants[THRESHOLD]; + size_t size = 33; + secp256k1_scalar privcoeff[N_SIGNERS][THRESHOLD]; + secp256k1_pubkey pubcoeff[N_SIGNERS][THRESHOLD]; + secp256k1_pubkey pubkeys[N_SIGNERS]; + secp256k1_frost_share shares[N_SIGNERS][N_SIGNERS]; + secp256k1_frost_share agg_shares[N_SIGNERS]; + secp256k1_scalar l; secp256k1_scalar s1, s2; - secp256k1_xonly_pubkey combined_pk; secp256k1_gej rj; secp256k1_ge rp; + secp256k1_keypair keypair; + secp256k1_frost_secnonce k; + secp256k1_frost_keygen_session sessions[N_SIGNERS]; + int i, j; - secp256k1_testrand256(sk1); - secp256k1_testrand256(sk2); - secp256k1_testrand256(sk3); /* Round 1.1, 1.2, 1.3, and 1.4 */ - CHECK(secp256k1_frost_keygen_init(ctx, coefficients1, commitments1, 2, 3, sk1)); - CHECK(secp256k1_frost_keygen_init(ctx, coefficients2, commitments2, 2, 3, sk2)); - CHECK(secp256k1_frost_keygen_init(ctx, coefficients3, commitments3, 2, 3, sk3)); + for (i = 0; i < N_SIGNERS; i++) { + secp256k1_testrand256(sk); + CHECK(secp256k1_frost_keygen_init(ctx, &sessions[i], privcoeff[i], pubcoeff[i], THRESHOLD, N_SIGNERS, i+1, sk)); + pubkeys[i] = sessions[i].coeff_pk; + } + /* Round 2.4 */ + for (i = 0; i < N_SIGNERS; i++) { + CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &sessions[i], pubkeys)); + } /* Round 2.1 */ - secp256k1_frost_generate_shares(shares1, coefficients1, 2, 3); - secp256k1_frost_generate_shares(shares2, coefficients2, 2, 3); - secp256k1_frost_generate_shares(shares3, coefficients3, 2, 3); + for (i = 0; i < N_SIGNERS; i++) { + secp256k1_frost_generate_shares(shares[i], privcoeff[i], &sessions[i]); + } /* Round 2.3 */ - share_buf[0] = shares1[0]; - share_buf[1] = shares2[0]; - share_buf[2] = shares3[0]; - secp256k1_frost_aggregate_shares(&agg1, share_buf, 3); - share_buf[0] = shares1[1]; - share_buf[1] = shares2[1]; - share_buf[2] = shares3[1]; - secp256k1_frost_aggregate_shares(&agg2, share_buf, 3); - share_buf[0] = shares1[2]; - share_buf[1] = shares2[2]; - share_buf[2] = shares3[2]; - secp256k1_frost_aggregate_shares(&agg3, share_buf, 3); - /* Round 2.4 */ - key_buf[0] = commitments1[0]; - key_buf[1] = commitments2[0]; - key_buf[2] = commitments3[0]; - CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &combined_pk, key_buf, 3)); + for (i = 0; i < N_SIGNERS; i++) { + secp256k1_frost_share rec_shares[N_SIGNERS]; + + for (j = 0; j < N_SIGNERS; j++) { + rec_shares[j] = shares[j][sessions[i].my_index - 1]; + } + + /* TODO: pull participant share from session */ + secp256k1_frost_aggregate_shares(&agg_shares[i], rec_shares, &sessions[i]); + } /* Reconstruct secret */ - participants[0] = 1; - participants[1] = 2; - secp256k1_frost_lagrange_coefficient(&l1, participants, 2, 1); - secp256k1_frost_lagrange_coefficient(&l2, participants, 2, 2); - secp256k1_scalar_set_b32(&s1, agg1.data, NULL); - secp256k1_scalar_set_b32(&s2, agg2.data, NULL); - secp256k1_scalar_mul(&s1, &s1, &l1); - secp256k1_scalar_mul(&s2, &s2, &l2); - secp256k1_scalar_add(&s1, &s1, &s2); + for (i = 0; i < THRESHOLD; i++) { + participants[i] = sessions[i].my_index; + } + secp256k1_scalar_clear(&s2); + for (i = 0; i < THRESHOLD; i++) { + secp256k1_frost_lagrange_coefficient(&l, participants, THRESHOLD, sessions[i].my_index); + secp256k1_scalar_set_b32(&s1, agg_shares[i].data, NULL); + secp256k1_scalar_mul(&s1, &s1, &l); + secp256k1_scalar_add(&s2, &s2, &s1); + } /* Test secret */ - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s1); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s2); secp256k1_ge_set_gej(&rp, &rj); - secp256k1_xonly_pubkey_save(&key_buf[0], &rp); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk1, &key_buf[0])); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &combined_pk)); - CHECK(secp256k1_memcmp_var(pk1, pk2, sizeof(pk1)) == 0); - secp256k1_scalar_clear(&s2); - secp256k1_scalar_add(&s2, &s2, &coefficients1[0]); - secp256k1_scalar_add(&s2, &s2, &coefficients2[0]); - secp256k1_scalar_add(&s2, &s2, &coefficients3[0]); + secp256k1_pubkey_save(&pubkeys[0], &rp); + CHECK(secp256k1_ec_pubkey_serialize(ctx, pk1, &size, &pubkeys[0], SECP256K1_EC_COMPRESSED)); + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); + CHECK(secp256k1_memcmp_var(&pk1[1], pk2, 32) == 0); + secp256k1_scalar_clear(&s1); + for (i = 0; i < N_SIGNERS; i++) { + secp256k1_scalar_add(&s1, &s1, &privcoeff[i][0]); + } CHECK(secp256k1_scalar_eq(&s1, &s2)); + + /* Test signing */ + secp256k1_testrand256(msg); + + secp256k1_scalar_get_b32(sk, &s1); + CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); + CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL)); + CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &sessions[0].combined_pk)); + + /* Generate nonces */ + /* TODO: need a noncegen session object */ + /* TODO: use separate ID for each participant */ + secp256k1_testrand256(id); + for (i = 0; i < THRESHOLD; i++) { + secp256k1_nonce_function_frost(&k, id, agg_shares[i].data, msg, pk2, frost_algo, 9, NULL); + secp256k1_scalar_set_b32(&s1, k.data, NULL); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s1); + secp256k1_ge_set_gej(&rp, &rj); + secp256k1_pubkey_save(&pubkeys[i], &rp); + } + sessions[0].n_signers = THRESHOLD; + CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &sessions[0], pubkeys)); + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); + /* sign */ + for (i = 0; i < THRESHOLD; i++) { + /* compute challenge hash */ + secp256k1_schnorrsig_challenge(&s2, pk2, msg, &pk1[1]); + + secp256k1_scalar_set_b32(&s1, agg_shares[i].data, NULL); + secp256k1_frost_lagrange_coefficient(&l, participants, THRESHOLD, sessions[i].my_index); + secp256k1_scalar_mul(&s1, &s1, &l); + secp256k1_scalar_mul(&s2, &s2, &s1); + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); + secp256k1_nonce_function_frost(&k, id, agg_shares[i].data, msg, &pk1[1], frost_algo, 9, NULL); + secp256k1_scalar_set_b32(&s1, k.data, NULL); + if (sessions[0].pk_parity) { + secp256k1_scalar_negate(&s1, &s1); + + } + secp256k1_scalar_add(&s2, &s2, &s1); + secp256k1_scalar_get_b32(p_sigs[i], &s2); + } + /* combine sigs */ + secp256k1_scalar_clear(&s1); + for (i = 0; i < THRESHOLD; i++) { + secp256k1_scalar_set_b32(&s2, p_sigs[i], NULL); + secp256k1_scalar_add(&s1, &s1, &s2); + } + secp256k1_scalar_get_b32(&sig[32], &s1); + memcpy(&sig[0], pk2, 32); + + CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &sessions[1].combined_pk)); } #endif /* SECP256K1_MODULE_FROST_TESTS_H */