test_frost.c (7130B)
1 #include <stdio.h> 2 #include <string.h> 3 #include "frost_high.h" 4 #include "keygen.h" 5 #include "frost_verify.h" 6 #include <time.h> 7 #include <gnunet/gnunet_util_lib.h> 8 9 static void 10 distributed_key_generation (struct FROST_KeyPair key_pairs[], 11 const struct FROST_DkgContextString *context_string, 12 uint8_t num_of_participants, 13 uint8_t threshold) 14 { 15 /* === Create shares and commitments === */ 16 struct FROST_DkgCommitment dkg_commitments[num_of_participants]; 17 struct FROST_DkgShare dkg_shares[num_of_participants][num_of_participants]; 18 19 for (int i = 0; i < num_of_participants; i++) 20 { 21 uint8_t my_index = i + 1; 22 FROST_initialize_dkg_commitment (&dkg_commitments[i], my_index, 23 threshold); 24 25 26 27 FROST_keygen_begin (&dkg_commitments[i], 28 (struct FROST_DkgShare *) &dkg_shares[i], 29 context_string, 30 NULL, 31 my_index, 32 num_of_participants, 33 threshold); 34 } 35 36 /* === Send commitments === */ 37 38 /* === Verify commitments received === */ 39 for (int i = 0; i < num_of_participants; i++) 40 { 41 GNUNET_assert (1 == FROST_keygen_validate_commitment ( 42 &dkg_commitments[i], 43 NULL, 44 num_of_participants)); 45 } 46 47 48 /* === Send shares === */ 49 /* === Receive shares === */ 50 51 /* === Compute my key share === */ 52 for (int i = 0; i < num_of_participants; i++) 53 { 54 uint8_t my_index = i + 1; // receivers-index 55 56 // Rearrange shares 57 struct FROST_DkgShare sorted_shares[num_of_participants]; 58 for (int j = 0; j < num_of_participants; j++) 59 { 60 if (j != my_index - 1) 61 { 62 // Verify received share against commitments 63 GNUNET_assert (FROST_keygen_validate_share (&dkg_commitments[j], 64 &dkg_shares[j][i], 65 my_index)); 66 } 67 68 FROST_scalar_copy_to (&sorted_shares[j].share, 69 &dkg_shares[j][i].share); 70 sorted_shares[j].identifier = i + 1; 71 } 72 73 FROST_keygen_finalize (&key_pairs[i], my_index, sorted_shares, 74 dkg_commitments, num_of_participants); 75 } 76 77 // Free dkg commitments 78 FROST_free_dkg_commitment (dkg_commitments, 79 num_of_participants); 80 } 81 82 83 static int 84 get_my_key_pair (const struct FROST_KeyPair shares[], 85 uint8_t id, 86 uint8_t n) 87 { 88 for (int i = 0; i < n; i++) 89 { 90 if (id == shares[i].identifier) 91 { 92 return i; 93 } 94 } 95 return -1; 96 } 97 98 // https://www.tutorialspoint.com/c_standard_library/c_function_qsort.htm 99 static int 100 cmp_int (const void *a, const void *b) 101 { 102 return (*(uint8_t*) a - *(uint8_t*) b); 103 } 104 105 106 /* 107 */ 108 static void 109 get_rnd_participants (uint8_t participants[], 110 uint8_t t, 111 uint8_t n) 112 { 113 GNUNET_assert (n >= t); 114 115 memset (participants, 0, t * sizeof (uint8_t)); 116 for (int i = 0; i < t; i++) 117 { 118 int check = 1; 119 while (check != 0) 120 { 121 check = 0; 122 uint32_t x = randombytes_random () % n + 1; 123 124 for (int j = 0; j < t; j++) 125 { 126 if (x == participants[j] || x == 0) 127 { 128 check = 1; 129 } 130 } 131 if (0 == check) 132 { 133 uint8_t y = (uint8_t) x; 134 participants[i] = y; 135 } 136 } 137 } 138 139 qsort (participants, t, sizeof (uint8_t), cmp_int); 140 } 141 142 143 int 144 main (void) 145 { 146 GNUNET_log_setup ("WARNING", 147 NULL, 148 NULL); 149 // Init crypto library 150 if (0 != FROST_init ()) 151 return 1; 152 153 // ToDo: what if t is '0' 154 uint8_t t = 7; 155 uint8_t n = 19; 156 157 // === Generate shares and public key === 158 struct FROST_KeyPair key_pairs[n]; 159 160 struct FROST_Scalar rnd; 161 FROST_scalar_random (&rnd); 162 163 struct FROST_ShortHashState state; 164 FROST_short_hash_init (&state); 165 FROST_short_hash_update_fixed (&state, 166 &rnd, 167 sizeof (rnd)); 168 169 struct FROST_DkgContextString context_string; 170 FROST_short_hash_final (&state, 171 &context_string.con_str); 172 173 // FROST_trusted_dealer_keygen (key_pairs, n, t); 174 distributed_key_generation (key_pairs, &context_string, n, t); 175 176 177 // === SA: Get a message === 178 char input[] = "This is a very important message!!!"; 179 180 struct FROST_MessageHash mh; 181 FROST_message_to_hash (&mh, input, strlen (input)); 182 183 184 // === SA: Choose participants === 185 // ToDo: Better solution for choosing rnd participants? 186 uint8_t participants[t]; 187 get_rnd_participants (participants, t, n); 188 189 190 // === Round One / Preprocess - All: Generate nonces and commitments === 191 struct FROST_Commitment commitment_list[t]; 192 struct FROST_Nonce nonces[t]; 193 for (uint8_t i = 0; i < t; i++) 194 { 195 int index = get_my_key_pair (key_pairs, participants[i], n); 196 197 struct FROST_CommitmentSeed seed; 198 FROST_get_random_seed (&seed); 199 200 FROST_generate_nonce_and_commitment (&nonces[i], 201 &commitment_list[i], 202 &mh, 203 &seed); 204 205 commitment_list[i].identifier = key_pairs[index].identifier; 206 } 207 208 // SA prepares the commitments and sends them to all participants, together 209 // with the message 210 // FROST_send_to_participant 211 212 // SA prepares to collect all shares 213 struct FROST_SignatureShare sig_shares[t]; 214 215 216 // === Round Two / Sign - ALL: === 217 for (uint8_t i = 0; i < t; i++) 218 { 219 int index = get_my_key_pair (key_pairs, participants[i], n); 220 221 // Validate all commitments, received from SA 222 for (uint8_t j = 0; j < t; j++) 223 { 224 GNUNET_assert (FROST_validate_commitment (&commitment_list[j])); 225 } 226 227 228 // Sign message 229 GNUNET_assert (FROST_sign_message_hash (&sig_shares[i], 230 &mh, 231 commitment_list, 232 t, 233 &key_pairs[index], 234 &nonces[i])); 235 236 // Send sig_share to SA 237 } 238 239 240 // === SA: verify all signature shares === 241 for (uint8_t i = 0; i < t; i++) 242 { 243 GNUNET_assert (FROST_verify_signature_share (&commitment_list[i], 244 &sig_shares[i], 245 commitment_list, t, 246 &key_pairs[i].group_pk, 247 &mh)); 248 } 249 250 // === SA: aggregate all sig shares and computes final signature === 251 struct FROST_Signature sig; 252 FROST_compose_signature (&sig, commitment_list, sig_shares, t, &mh); 253 254 255 // === SA: publish sig === 256 257 // === Verify signature === 258 if (GNUNET_OK == FROST_verify_signature (&key_pairs[0].group_pk, 259 &sig, 260 &mh)) 261 return 0; 262 263 return 1; 264 }