|
4 | 4 | #include "include/secp256k1_frost.h"
|
5 | 5 | #include <secp256k1_musig.h>
|
6 | 6 |
|
| 7 | + /* Number of public keys involved in creating the aggregate signature */ |
| 8 | +#define N_SIGNERS 3 |
| 9 | + |
| 10 | + /* Threshold required in creating the aggregate signature */ |
| 11 | +#define THRESHOLD 2 |
| 12 | + |
7 | 13 | void run_frost_tests(void) {
|
8 |
| - unsigned char sk1[32]; |
9 |
| - unsigned char sk2[32]; |
10 |
| - unsigned char sk3[32]; |
11 |
| - unsigned char pk1[32]; |
12 |
| - unsigned char pk2[32]; |
13 |
| - size_t participants[2]; |
14 |
| - secp256k1_scalar coefficients1[2]; |
15 |
| - secp256k1_scalar coefficients2[2]; |
16 |
| - secp256k1_scalar coefficients3[2]; |
17 |
| - secp256k1_xonly_pubkey commitments1[2]; |
18 |
| - secp256k1_xonly_pubkey commitments2[2]; |
19 |
| - secp256k1_xonly_pubkey commitments3[2]; |
20 |
| - secp256k1_frost_share shares1[3]; |
21 |
| - secp256k1_frost_share shares2[3]; |
22 |
| - secp256k1_frost_share shares3[3]; |
23 |
| - secp256k1_frost_share agg1, agg2, agg3; |
24 |
| - secp256k1_frost_share share_buf[3]; |
25 |
| - secp256k1_xonly_pubkey key_buf[3]; |
26 |
| - secp256k1_scalar l1, l2; |
| 14 | + /* TODO: c.f. musig, example.c */ |
| 15 | + unsigned char pk1[33]; |
| 16 | + unsigned char pk2[33]; |
| 17 | + unsigned char sig[64]; |
| 18 | + unsigned char msg[32]; |
| 19 | + unsigned char id[32]; |
| 20 | + unsigned char sk[32]; |
| 21 | + unsigned char p_sigs[THRESHOLD][32]; |
| 22 | + size_t participants[THRESHOLD]; |
| 23 | + size_t size = 33; |
| 24 | + secp256k1_scalar privcoeff[N_SIGNERS][THRESHOLD]; |
| 25 | + secp256k1_pubkey pubcoeff[N_SIGNERS][THRESHOLD]; |
| 26 | + secp256k1_pubkey pubkeys[N_SIGNERS]; |
| 27 | + secp256k1_frost_share shares[N_SIGNERS][N_SIGNERS]; |
| 28 | + secp256k1_frost_share agg_shares[N_SIGNERS]; |
| 29 | + secp256k1_scalar l; |
27 | 30 | secp256k1_scalar s1, s2;
|
28 |
| - secp256k1_xonly_pubkey combined_pk; |
29 | 31 | secp256k1_gej rj;
|
30 | 32 | secp256k1_ge rp;
|
| 33 | + secp256k1_keypair keypair; |
| 34 | + secp256k1_frost_secnonce k; |
| 35 | + secp256k1_frost_keygen_session sessions[N_SIGNERS]; |
| 36 | + int i, j; |
31 | 37 |
|
32 |
| - secp256k1_testrand256(sk1); |
33 |
| - secp256k1_testrand256(sk2); |
34 |
| - secp256k1_testrand256(sk3); |
35 | 38 | /* Round 1.1, 1.2, 1.3, and 1.4 */
|
36 |
| - CHECK(secp256k1_frost_keygen_init(ctx, coefficients1, commitments1, 2, 3, sk1)); |
37 |
| - CHECK(secp256k1_frost_keygen_init(ctx, coefficients2, commitments2, 2, 3, sk2)); |
38 |
| - CHECK(secp256k1_frost_keygen_init(ctx, coefficients3, commitments3, 2, 3, sk3)); |
| 39 | + for (i = 0; i < N_SIGNERS; i++) { |
| 40 | + secp256k1_testrand256(sk); |
| 41 | + CHECK(secp256k1_frost_keygen_init(ctx, &sessions[i], privcoeff[i], pubcoeff[i], THRESHOLD, N_SIGNERS, i+1, sk)); |
| 42 | + pubkeys[i] = sessions[i].coeff_pk; |
| 43 | + } |
| 44 | + /* Round 2.4 */ |
| 45 | + for (i = 0; i < N_SIGNERS; i++) { |
| 46 | + CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &sessions[i], pubkeys)); |
| 47 | + } |
39 | 48 | /* Round 2.1 */
|
40 |
| - secp256k1_frost_generate_shares(shares1, coefficients1, 2, 3); |
41 |
| - secp256k1_frost_generate_shares(shares2, coefficients2, 2, 3); |
42 |
| - secp256k1_frost_generate_shares(shares3, coefficients3, 2, 3); |
| 49 | + for (i = 0; i < N_SIGNERS; i++) { |
| 50 | + secp256k1_frost_generate_shares(shares[i], privcoeff[i], &sessions[i]); |
| 51 | + } |
43 | 52 | /* Round 2.3 */
|
44 |
| - share_buf[0] = shares1[0]; |
45 |
| - share_buf[1] = shares2[0]; |
46 |
| - share_buf[2] = shares3[0]; |
47 |
| - secp256k1_frost_aggregate_shares(&agg1, share_buf, 3); |
48 |
| - share_buf[0] = shares1[1]; |
49 |
| - share_buf[1] = shares2[1]; |
50 |
| - share_buf[2] = shares3[1]; |
51 |
| - secp256k1_frost_aggregate_shares(&agg2, share_buf, 3); |
52 |
| - share_buf[0] = shares1[2]; |
53 |
| - share_buf[1] = shares2[2]; |
54 |
| - share_buf[2] = shares3[2]; |
55 |
| - secp256k1_frost_aggregate_shares(&agg3, share_buf, 3); |
56 |
| - /* Round 2.4 */ |
57 |
| - key_buf[0] = commitments1[0]; |
58 |
| - key_buf[1] = commitments2[0]; |
59 |
| - key_buf[2] = commitments3[0]; |
60 |
| - CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &combined_pk, key_buf, 3)); |
| 53 | + for (i = 0; i < N_SIGNERS; i++) { |
| 54 | + secp256k1_frost_share rec_shares[N_SIGNERS]; |
| 55 | + |
| 56 | + for (j = 0; j < N_SIGNERS; j++) { |
| 57 | + rec_shares[j] = shares[j][sessions[i].my_index - 1]; |
| 58 | + } |
| 59 | + |
| 60 | + /* TODO: pull participant share from session */ |
| 61 | + secp256k1_frost_aggregate_shares(&agg_shares[i], rec_shares, &sessions[i]); |
| 62 | + } |
61 | 63 |
|
62 | 64 | /* Reconstruct secret */
|
63 |
| - participants[0] = 1; |
64 |
| - participants[1] = 2; |
65 |
| - secp256k1_frost_lagrange_coefficient(&l1, participants, 2, 1); |
66 |
| - secp256k1_frost_lagrange_coefficient(&l2, participants, 2, 2); |
67 |
| - secp256k1_scalar_set_b32(&s1, agg1.data, NULL); |
68 |
| - secp256k1_scalar_set_b32(&s2, agg2.data, NULL); |
69 |
| - secp256k1_scalar_mul(&s1, &s1, &l1); |
70 |
| - secp256k1_scalar_mul(&s2, &s2, &l2); |
71 |
| - secp256k1_scalar_add(&s1, &s1, &s2); |
| 65 | + for (i = 0; i < THRESHOLD; i++) { |
| 66 | + participants[i] = sessions[i].my_index; |
| 67 | + } |
| 68 | + secp256k1_scalar_clear(&s2); |
| 69 | + for (i = 0; i < THRESHOLD; i++) { |
| 70 | + secp256k1_frost_lagrange_coefficient(&l, participants, THRESHOLD, sessions[i].my_index); |
| 71 | + secp256k1_scalar_set_b32(&s1, agg_shares[i].data, NULL); |
| 72 | + secp256k1_scalar_mul(&s1, &s1, &l); |
| 73 | + secp256k1_scalar_add(&s2, &s2, &s1); |
| 74 | + } |
72 | 75 |
|
73 | 76 | /* Test secret */
|
74 |
| - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s1); |
| 77 | + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s2); |
75 | 78 | secp256k1_ge_set_gej(&rp, &rj);
|
76 |
| - secp256k1_xonly_pubkey_save(&key_buf[0], &rp); |
77 |
| - CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk1, &key_buf[0])); |
78 |
| - CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &combined_pk)); |
79 |
| - CHECK(secp256k1_memcmp_var(pk1, pk2, sizeof(pk1)) == 0); |
80 |
| - secp256k1_scalar_clear(&s2); |
81 |
| - secp256k1_scalar_add(&s2, &s2, &coefficients1[0]); |
82 |
| - secp256k1_scalar_add(&s2, &s2, &coefficients2[0]); |
83 |
| - secp256k1_scalar_add(&s2, &s2, &coefficients3[0]); |
| 79 | + secp256k1_pubkey_save(&pubkeys[0], &rp); |
| 80 | + CHECK(secp256k1_ec_pubkey_serialize(ctx, pk1, &size, &pubkeys[0], SECP256K1_EC_COMPRESSED)); |
| 81 | + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); |
| 82 | + CHECK(secp256k1_memcmp_var(&pk1[1], pk2, 32) == 0); |
| 83 | + secp256k1_scalar_clear(&s1); |
| 84 | + for (i = 0; i < N_SIGNERS; i++) { |
| 85 | + secp256k1_scalar_add(&s1, &s1, &privcoeff[i][0]); |
| 86 | + } |
84 | 87 | CHECK(secp256k1_scalar_eq(&s1, &s2));
|
| 88 | + |
| 89 | + /* Test signing */ |
| 90 | + secp256k1_testrand256(msg); |
| 91 | + |
| 92 | + secp256k1_scalar_get_b32(sk, &s1); |
| 93 | + CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); |
| 94 | + CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL)); |
| 95 | + CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &sessions[0].combined_pk)); |
| 96 | + |
| 97 | + /* Generate nonces */ |
| 98 | + /* TODO: need a noncegen session object */ |
| 99 | + /* TODO: use separate ID for each participant */ |
| 100 | + secp256k1_testrand256(id); |
| 101 | + for (i = 0; i < THRESHOLD; i++) { |
| 102 | + secp256k1_nonce_function_frost(&k, id, agg_shares[i].data, msg, pk2, frost_algo, 9, NULL); |
| 103 | + secp256k1_scalar_set_b32(&s1, k.data, NULL); |
| 104 | + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &s1); |
| 105 | + secp256k1_ge_set_gej(&rp, &rj); |
| 106 | + secp256k1_pubkey_save(&pubkeys[i], &rp); |
| 107 | + } |
| 108 | + sessions[0].n_signers = THRESHOLD; |
| 109 | + CHECK(secp256k1_frost_pubkey_combine(ctx, NULL, &sessions[0], pubkeys)); |
| 110 | + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); |
| 111 | + /* sign */ |
| 112 | + for (i = 0; i < THRESHOLD; i++) { |
| 113 | + /* compute challenge hash */ |
| 114 | + secp256k1_schnorrsig_challenge(&s2, pk2, msg, &pk1[1]); |
| 115 | + |
| 116 | + secp256k1_scalar_set_b32(&s1, agg_shares[i].data, NULL); |
| 117 | + secp256k1_frost_lagrange_coefficient(&l, participants, THRESHOLD, sessions[i].my_index); |
| 118 | + secp256k1_scalar_mul(&s1, &s1, &l); |
| 119 | + secp256k1_scalar_mul(&s2, &s2, &s1); |
| 120 | + CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk2, &sessions[0].combined_pk)); |
| 121 | + secp256k1_nonce_function_frost(&k, id, agg_shares[i].data, msg, &pk1[1], frost_algo, 9, NULL); |
| 122 | + secp256k1_scalar_set_b32(&s1, k.data, NULL); |
| 123 | + if (sessions[0].pk_parity) { |
| 124 | + secp256k1_scalar_negate(&s1, &s1); |
| 125 | + |
| 126 | + } |
| 127 | + secp256k1_scalar_add(&s2, &s2, &s1); |
| 128 | + secp256k1_scalar_get_b32(p_sigs[i], &s2); |
| 129 | + } |
| 130 | + /* combine sigs */ |
| 131 | + secp256k1_scalar_clear(&s1); |
| 132 | + for (i = 0; i < THRESHOLD; i++) { |
| 133 | + secp256k1_scalar_set_b32(&s2, p_sigs[i], NULL); |
| 134 | + secp256k1_scalar_add(&s1, &s1, &s2); |
| 135 | + } |
| 136 | + secp256k1_scalar_get_b32(&sig[32], &s1); |
| 137 | + memcpy(&sig[0], pk2, 32); |
| 138 | + |
| 139 | + CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &sessions[1].combined_pk)); |
85 | 140 | }
|
86 | 141 |
|
87 | 142 | #endif /* SECP256K1_MODULE_FROST_TESTS_H */
|
0 commit comments