Skip to content

Commit

Permalink
Verify proofs-of-knowledge
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseposner committed Aug 2, 2024
1 parent ef0f4aa commit 5937a43
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 24 deletions.
4 changes: 3 additions & 1 deletion examples/frost.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_se
secp256k1_frost_share shares[N_SIGNERS][N_SIGNERS];
const secp256k1_pubkey *vss_commitments[N_SIGNERS];
const unsigned char *ids[N_SIGNERS];
const unsigned char *poks[N_SIGNERS];

for (i = 0; i < N_SIGNERS; i++) {
vss_commitments[i] = signer[i].vss_commitment;
ids[i] = signer[i].id;
poks[i] = signer[i].pok;
}

for (i = 0; i < N_SIGNERS; i++) {
Expand All @@ -99,7 +101,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, N_SIGNERS, THRESHOLD, signer[i].id)) {
if (!secp256k1_frost_share_agg(ctx, &signer_secrets[i].agg_share, pk, assigned_shares, vss_commitments, poks, N_SIGNERS, THRESHOLD, signer[i].id)) {
return 0;
}
for (j = 0; j < N_SIGNERS; j++) {
Expand Down
3 changes: 2 additions & 1 deletion include/secp256k1_frost.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,11 @@ SECP256K1_API int secp256k1_frost_share_agg(
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(8);
) 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);

/** Verifies a share received during a key generation session
*
Expand Down
5 changes: 4 additions & 1 deletion src/ctime_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
unsigned char id[2][33];
const unsigned char *id_ptr[2];
size_t size = 33;
const unsigned char *pok_ptr[2];

id_ptr[0] = id[0];
id_ptr[1] = id[1];
Expand All @@ -406,6 +407,8 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
share_ptr[1] = &shares[1][0];
vss_ptr[0] = vss_commitment[0];
vss_ptr[1] = vss_commitment[1];
pok_ptr[0] = pok[0];
pok_ptr[1] = pok[1];

CHECK(secp256k1_keypair_create(ctx, &keypair, key));
CHECK(secp256k1_keypair_create(ctx, &keypair2, key2));
Expand All @@ -431,7 +434,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
SECP256K1_CHECKMEM_DEFINE(&vss_commitment[1][0], sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_DEFINE(&vss_commitment[1][1], sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_DEFINE(pok[0], 64);
ret = secp256k1_frost_share_agg(ctx, &agg_share, &agg_pk, share_ptr, vss_ptr, 2, 2, id_ptr[0]);
ret = secp256k1_frost_share_agg(ctx, &agg_share, &agg_pk, share_ptr, vss_ptr, pok_ptr, 2, 2, id_ptr[0]);
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
/* nonce_gen */
Expand Down
19 changes: 18 additions & 1 deletion src/modules/frost/keygen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,21 +385,24 @@ int secp256k1_frost_compute_pubshare(const secp256k1_context* ctx, secp256k1_pub
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, size_t n_shares, size_t threshold, const unsigned char *id33) {
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;
secp256k1_scalar acc;
size_t i;
int ret = 1;
secp256k1_sha256 sha;
unsigned char buf[32];

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);
ARG_CHECK(id33 != NULL);
ARG_CHECK(n_shares > 1);
Expand All @@ -409,6 +412,20 @@ int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_shar
return 0;
}

/* Verify proofs-of-knowledge */
secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"FROST/KeygenPoK", sizeof("FROST/KeygenPoK") - 1);
secp256k1_sha256_finalize(&sha, buf);
for (i = 0; i < n_shares; i++) {
secp256k1_xonly_pubkey pk;

if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &pk, NULL, &vss_commitments[i][0])) {
return 0;
}
if (!secp256k1_schnorrsig_verify(ctx, pok64s[i], buf, 32, &pk)) {
return 0;
}
}

secp256k1_scalar_clear(&acc);
for (i = 0; i < n_shares; i++) {
secp256k1_scalar share_i;
Expand Down
58 changes: 38 additions & 20 deletions src/modules/frost/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void frost_simple_test(void) {
int i, j;
unsigned char id[5][33];
const unsigned char *id_ptr[5];
const unsigned char *pok_ptr[5];

for (i = 0; i < 5; i++) {
secp256k1_testrand256(buf[i]);
Expand All @@ -66,6 +67,7 @@ void frost_simple_test(void) {
pubnonce_ptr[i] = &pubnonce[i];
partial_sig_ptr[i] = &partial_sig[i];
id_ptr[i] = id[i];
pok_ptr[i] = pok[i];

CHECK(frost_create_pk(id[i], sk[i]));
}
Expand All @@ -78,7 +80,7 @@ void frost_simple_test(void) {
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, 5, 3, id_ptr[i]) == 1);
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
}

secp256k1_testrand256(msg);
Expand Down Expand Up @@ -177,6 +179,8 @@ void frost_api_tests(void) {
int i, j;
unsigned char id[5][33];
const unsigned char *id_ptr[5];
const unsigned char *pok_ptr[5];
const unsigned char *invalid_pok_ptr[5];

/** setup **/
memset(max64, 0xff, sizeof(max64));
Expand Down Expand Up @@ -205,13 +209,16 @@ void frost_api_tests(void) {
partial_sig_ptr[i] = &partial_sig[i];
invalid_partial_sig_ptr[i] = &partial_sig[i];
id_ptr[i] = id[i];
pok_ptr[i] = pok[i];
invalid_pok_ptr[i] = pok[i];
secp256k1_testrand256(session_id[i]);
secp256k1_testrand256(seed[i]);
secp256k1_testrand256(sk[i]);
CHECK(frost_create_pk(id[i], sk[i]));
}
invalid_pubnonce_ptr[0] = &invalid_pubnonce;
invalid_partial_sig_ptr[0] = &invalid_partial_sig;
invalid_pok_ptr[0] = max64;
for (i = 0; i < 5; i++) {
for (j = 0; j < 3; j++) {
invalid_vss_commitment[i][j] = invalid_vss_pk;
Expand Down Expand Up @@ -257,41 +264,48 @@ 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, 5, 3, id_ptr[i]) == 1);
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, NULL, &agg_pk, share_ptr, vss_ptr, 5, 3, id_ptr[i]));
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, share_ptr, vss_ptr, 5, 3, id_ptr[i]));
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(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(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, 5, 3, id_ptr[i]));
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, 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(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(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(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(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, 5, 3, id_ptr[i]));
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, 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);
/* TODO: fix test */
/* CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, invalid_vss_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, vss_ptr, 5, 3, NULL));
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(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, 5, 3, id_ptr[i]));
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(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, 0, 3, id_ptr[i]));
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, 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, 0, 3, id_ptr[i]));
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(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, 5, 0, id_ptr[i]));
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, 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, 5, 0, id_ptr[i]));
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, 5, 3, id_ptr[i]) == 1);
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
}

/* Share verification */
Expand Down Expand Up @@ -701,13 +715,15 @@ void frost_tweak_test(void) {
int i, j;
unsigned char id[5][33];
const unsigned char *id_ptr[5];
const unsigned char *pok_ptr[5];

/* Key Setup */
for (i = 0; i < 5; i++) {
secp256k1_testrand256(seed[i]);
secp256k1_testrand256(sk[i]);
vss_ptr[i] = vss_commitment[i];
id_ptr[i] = id[i];
pok_ptr[i] = pok[i];

CHECK(frost_create_pk(id[i], sk[i]));
}
Expand All @@ -720,7 +736,7 @@ void frost_tweak_test(void) {
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, 5, 3, id_ptr[i]) == 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);
}

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]);
Expand Down Expand Up @@ -768,10 +784,12 @@ void frost_dkg_test_helper(secp256k1_frost_share *agg_share, secp256k1_xonly_pub
secp256k1_frost_share shares[5][5];
const secp256k1_frost_share *share_ptr[5];
int i, j;
const unsigned char *pok_ptr[5];

for (i = 0; i < 5; i++) {
secp256k1_testrand256(seed[i]);
vss_ptr[i] = vss_commitment[i];
pok_ptr[i] = pok[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);
Expand All @@ -780,7 +798,7 @@ 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, 5, 3, ids33[i]) == 1);
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, ids33[i]) == 1);
}
}

Expand Down

0 comments on commit 5937a43

Please sign in to comment.