frosix

Multiparty signature service (experimental)
Log | Files | Refs | README | LICENSE

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 }