Skip to content

Commit 5937a43

Browse files
committed
Verify proofs-of-knowledge
1 parent ef0f4aa commit 5937a43

File tree

5 files changed

+65
-24
lines changed

5 files changed

+65
-24
lines changed

examples/frost.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_se
7575
secp256k1_frost_share shares[N_SIGNERS][N_SIGNERS];
7676
const secp256k1_pubkey *vss_commitments[N_SIGNERS];
7777
const unsigned char *ids[N_SIGNERS];
78+
const unsigned char *poks[N_SIGNERS];
7879

7980
for (i = 0; i < N_SIGNERS; i++) {
8081
vss_commitments[i] = signer[i].vss_commitment;
8182
ids[i] = signer[i].id;
83+
poks[i] = signer[i].pok;
8284
}
8385

8486
for (i = 0; i < N_SIGNERS; i++) {
@@ -99,7 +101,7 @@ int create_shares(const secp256k1_context* ctx, struct signer_secrets *signer_se
99101
assigned_shares[j] = &shares[j][i];
100102
}
101103
/* Each participant aggregates the shares they received. */
102-
if (!secp256k1_frost_share_agg(ctx, &signer_secrets[i].agg_share, pk, assigned_shares, vss_commitments, N_SIGNERS, THRESHOLD, signer[i].id)) {
104+
if (!secp256k1_frost_share_agg(ctx, &signer_secrets[i].agg_share, pk, assigned_shares, vss_commitments, poks, N_SIGNERS, THRESHOLD, signer[i].id)) {
103105
return 0;
104106
}
105107
for (j = 0; j < N_SIGNERS; j++) {

include/secp256k1_frost.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,11 @@ SECP256K1_API int secp256k1_frost_share_agg(
255255
secp256k1_xonly_pubkey *agg_pk,
256256
const secp256k1_frost_share * const *shares,
257257
const secp256k1_pubkey * const *vss_commitments,
258+
const unsigned char * const* pok64s,
258259
size_t n_shares,
259260
size_t threshold,
260261
const unsigned char *id33
261-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8);
262+
) 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);
262263

263264
/** Verifies a share received during a key generation session
264265
*

src/ctime_tests.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
383383
unsigned char id[2][33];
384384
const unsigned char *id_ptr[2];
385385
size_t size = 33;
386+
const unsigned char *pok_ptr[2];
386387

387388
id_ptr[0] = id[0];
388389
id_ptr[1] = id[1];
@@ -406,6 +407,8 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
406407
share_ptr[1] = &shares[1][0];
407408
vss_ptr[0] = vss_commitment[0];
408409
vss_ptr[1] = vss_commitment[1];
410+
pok_ptr[0] = pok[0];
411+
pok_ptr[1] = pok[1];
409412

410413
CHECK(secp256k1_keypair_create(ctx, &keypair, key));
411414
CHECK(secp256k1_keypair_create(ctx, &keypair2, key2));
@@ -431,7 +434,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
431434
SECP256K1_CHECKMEM_DEFINE(&vss_commitment[1][0], sizeof(secp256k1_pubkey));
432435
SECP256K1_CHECKMEM_DEFINE(&vss_commitment[1][1], sizeof(secp256k1_pubkey));
433436
SECP256K1_CHECKMEM_DEFINE(pok[0], 64);
434-
ret = secp256k1_frost_share_agg(ctx, &agg_share, &agg_pk, share_ptr, vss_ptr, 2, 2, id_ptr[0]);
437+
ret = secp256k1_frost_share_agg(ctx, &agg_share, &agg_pk, share_ptr, vss_ptr, pok_ptr, 2, 2, id_ptr[0]);
435438
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
436439
CHECK(ret == 1);
437440
/* nonce_gen */

src/modules/frost/keygen_impl.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -385,21 +385,24 @@ int secp256k1_frost_compute_pubshare(const secp256k1_context* ctx, secp256k1_pub
385385
return 1;
386386
}
387387

388-
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) {
388+
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) {
389389
secp256k1_frost_pubkey_combine_ecmult_data pubkey_combine_ecmult_data;
390390
secp256k1_gej pkj;
391391
secp256k1_ge pkp;
392392
int pk_parity;
393393
secp256k1_scalar acc;
394394
size_t i;
395395
int ret = 1;
396+
secp256k1_sha256 sha;
397+
unsigned char buf[32];
396398

397399
VERIFY_CHECK(ctx != NULL);
398400
ARG_CHECK(agg_share != NULL);
399401
memset(agg_share, 0, sizeof(*agg_share));
400402
ARG_CHECK(agg_pk != NULL);
401403
memset(agg_pk, 0, sizeof(*agg_pk));
402404
ARG_CHECK(shares != NULL);
405+
ARG_CHECK(pok64s != NULL);
403406
ARG_CHECK(vss_commitments != NULL);
404407
ARG_CHECK(id33 != NULL);
405408
ARG_CHECK(n_shares > 1);
@@ -409,6 +412,20 @@ int secp256k1_frost_share_agg(const secp256k1_context* ctx, secp256k1_frost_shar
409412
return 0;
410413
}
411414

415+
/* Verify proofs-of-knowledge */
416+
secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"FROST/KeygenPoK", sizeof("FROST/KeygenPoK") - 1);
417+
secp256k1_sha256_finalize(&sha, buf);
418+
for (i = 0; i < n_shares; i++) {
419+
secp256k1_xonly_pubkey pk;
420+
421+
if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &pk, NULL, &vss_commitments[i][0])) {
422+
return 0;
423+
}
424+
if (!secp256k1_schnorrsig_verify(ctx, pok64s[i], buf, 32, &pk)) {
425+
return 0;
426+
}
427+
}
428+
412429
secp256k1_scalar_clear(&acc);
413430
for (i = 0; i < n_shares; i++) {
414431
secp256k1_scalar share_i;

src/modules/frost/tests_impl.h

+38-20
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ void frost_simple_test(void) {
5858
int i, j;
5959
unsigned char id[5][33];
6060
const unsigned char *id_ptr[5];
61+
const unsigned char *pok_ptr[5];
6162

6263
for (i = 0; i < 5; i++) {
6364
secp256k1_testrand256(buf[i]);
@@ -66,6 +67,7 @@ void frost_simple_test(void) {
6667
pubnonce_ptr[i] = &pubnonce[i];
6768
partial_sig_ptr[i] = &partial_sig[i];
6869
id_ptr[i] = id[i];
70+
pok_ptr[i] = pok[i];
6971

7072
CHECK(frost_create_pk(id[i], sk[i]));
7173
}
@@ -78,7 +80,7 @@ void frost_simple_test(void) {
7880
CHECK(secp256k1_frost_share_verify(CTX, 3, id_ptr[i], share_ptr[j], &vss_ptr[j]) == 1);
7981
CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[j], 3, id_ptr[j], vss_ptr, 5) == 1);
8082
}
81-
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 5, 3, id_ptr[i]) == 1);
83+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
8284
}
8385

8486
secp256k1_testrand256(msg);
@@ -177,6 +179,8 @@ void frost_api_tests(void) {
177179
int i, j;
178180
unsigned char id[5][33];
179181
const unsigned char *id_ptr[5];
182+
const unsigned char *pok_ptr[5];
183+
const unsigned char *invalid_pok_ptr[5];
180184

181185
/** setup **/
182186
memset(max64, 0xff, sizeof(max64));
@@ -205,13 +209,16 @@ void frost_api_tests(void) {
205209
partial_sig_ptr[i] = &partial_sig[i];
206210
invalid_partial_sig_ptr[i] = &partial_sig[i];
207211
id_ptr[i] = id[i];
212+
pok_ptr[i] = pok[i];
213+
invalid_pok_ptr[i] = pok[i];
208214
secp256k1_testrand256(session_id[i]);
209215
secp256k1_testrand256(seed[i]);
210216
secp256k1_testrand256(sk[i]);
211217
CHECK(frost_create_pk(id[i], sk[i]));
212218
}
213219
invalid_pubnonce_ptr[0] = &invalid_pubnonce;
214220
invalid_partial_sig_ptr[0] = &invalid_partial_sig;
221+
invalid_pok_ptr[0] = max64;
215222
for (i = 0; i < 5; i++) {
216223
for (j = 0; j < 3; j++) {
217224
invalid_vss_commitment[i][j] = invalid_vss_pk;
@@ -257,41 +264,48 @@ void frost_api_tests(void) {
257264
invalid_share_ptr[j] = &shares[j][i];
258265
}
259266
invalid_share_ptr[0] = &invalid_share;
260-
261-
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 5, 3, id_ptr[i]) == 1);
262-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, NULL, &agg_pk, share_ptr, vss_ptr, 5, 3, id_ptr[i]));
263-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, share_ptr, vss_ptr, 5, 3, id_ptr[i]));
267+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
268+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, invalid_pok_ptr, 5, 3, id_ptr[i]) == 0);
269+
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
270+
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
271+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, NULL, &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]));
272+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], NULL, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]));
264273
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
265-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, 5, 3, id_ptr[i]));
274+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, pok_ptr, 5, 3, id_ptr[i]));
275+
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
276+
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
277+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, pok_ptr, 5, 3, id_ptr[i]));
278+
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
279+
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
280+
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]));
281+
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
282+
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
283+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, NULL, 5, 3, id_ptr[i]));
266284
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
267285
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
268-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, 5, 3, id_ptr[i]));
286+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, NULL));
269287
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
270288
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
271-
/* TODO: fix test */
272-
/* CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, invalid_vss_ptr, 5, 3, id_ptr[i])); */
273-
/* CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0); */
274-
/* CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0); */
275-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 5, 3, NULL));
289+
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]));
276290
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
277291
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
278-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, invalid_share_ptr, vss_ptr, 5, 3, id_ptr[i]));
292+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 0, 3, id_ptr[i]));
279293
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
280294
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
281-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 0, 3, id_ptr[i]));
295+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, pok_ptr, 0, 3, id_ptr[i]));
282296
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
283297
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
284-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, NULL, vss_ptr, 0, 3, id_ptr[i]));
298+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 0, id_ptr[i]));
285299
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
286300
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
287-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 5, 0, id_ptr[i]));
301+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, pok_ptr, 5, 0, id_ptr[i]));
288302
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
289303
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
290-
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, NULL, 5, 0, id_ptr[i]));
304+
CHECK_ILLEGAL(CTX, secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, NULL, 5, 0, id_ptr[i]));
291305
CHECK(frost_memcmp_and_randomize(agg_share[i].data, zeros68, sizeof(agg_share[i].data)) == 0);
292306
CHECK(frost_memcmp_and_randomize(agg_pk.data, zeros68, sizeof(agg_pk.data)) == 0);
293307

294-
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, 5, 3, id_ptr[i]) == 1);
308+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
295309
}
296310

297311
/* Share verification */
@@ -701,13 +715,15 @@ void frost_tweak_test(void) {
701715
int i, j;
702716
unsigned char id[5][33];
703717
const unsigned char *id_ptr[5];
718+
const unsigned char *pok_ptr[5];
704719

705720
/* Key Setup */
706721
for (i = 0; i < 5; i++) {
707722
secp256k1_testrand256(seed[i]);
708723
secp256k1_testrand256(sk[i]);
709724
vss_ptr[i] = vss_commitment[i];
710725
id_ptr[i] = id[i];
726+
pok_ptr[i] = pok[i];
711727

712728
CHECK(frost_create_pk(id[i], sk[i]));
713729
}
@@ -720,7 +736,7 @@ void frost_tweak_test(void) {
720736
CHECK(secp256k1_frost_share_verify(CTX, 3, id_ptr[i], share_ptr[j], &vss_ptr[j]) == 1);
721737
CHECK(secp256k1_frost_compute_pubshare(CTX, &pubshare[j], 3, id_ptr[j], vss_ptr, 5) == 1);
722738
}
723-
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &P_xonly[0], share_ptr, vss_ptr, 5, 3, id_ptr[i]) == 1);
739+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], &P_xonly[0], share_ptr, vss_ptr, pok_ptr, 5, 3, id_ptr[i]) == 1);
724740
}
725741

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

772789
for (i = 0; i < 5; i++) {
773790
secp256k1_testrand256(seed[i]);
774791
vss_ptr[i] = vss_commitment[i];
792+
pok_ptr[i] = pok[i];
775793
}
776794
for (i = 0; i < 5; i++) {
777795
CHECK(secp256k1_frost_shares_gen(CTX, shares[i], vss_commitment[i], pok[i], seed[i], 3, 5, ids33) == 1);
@@ -780,7 +798,7 @@ void frost_dkg_test_helper(secp256k1_frost_share *agg_share, secp256k1_xonly_pub
780798
for (j = 0; j < 5; j++) {
781799
share_ptr[j] = &shares[j][i];
782800
}
783-
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], agg_pk, share_ptr, vss_ptr, 5, 3, ids33[i]) == 1);
801+
CHECK(secp256k1_frost_share_agg(CTX, &agg_share[i], agg_pk, share_ptr, vss_ptr, pok_ptr, 5, 3, ids33[i]) == 1);
784802
}
785803
}
786804

0 commit comments

Comments
 (0)