frosix

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

high_common.c (8239B)


      1 /*
      2   This file is part of Frosix
      3   Copyright (C) 2022, 2023 Joel Urech
      4 
      5   Frosix is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   Frosix is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   Frosix; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file high_common.c
     18  * @brief Implementations of function which are used for different tasks during the signing or key generation process.
     19  * @author Joel Urech
     20 */
     21 #include "high_common.h"
     22 
     23 /**
     24  * @brief Returns all participants from the commitment list.
     25  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-list-operations
     26  *
     27  * @param participants The resulting list of all participating participants
     28  * @param commitments The commitment list which we got from the 'SA'
     29  * @param commitments_len Length of the commitment list
     30 */
     31 static void
     32 participants_from_commitment_list (
     33   uint8_t participants[],
     34   const struct FROST_Commitment commitments[],
     35   uint8_t commitments_len)
     36 {
     37   for (uint8_t i = 0; i < commitments_len; i++)
     38   {
     39     participants[i] = commitments[i].identifier;
     40   }
     41 }
     42 
     43 /**
     44  * Computes the set of binding values for all participating participants.
     45  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-binding-factors-computation
     46 */
     47 void
     48 FROST_compute_binding_factors_ (
     49   struct FROST_BindingFactor binding_factors[],
     50   const struct FROST_Commitment commitments[],
     51   uint8_t commitments_len,
     52   const struct FROST_MessageHash *mh)
     53 {
     54   // H(group_commitment_list)
     55   struct FROST_HashState hash_state;
     56   FROST_hash_init (&hash_state);
     57 
     58   for (uint8_t i = 0; i < commitments_len; i++)
     59   {
     60     FROST_hash_uint8_update (&hash_state, commitments[i].identifier);
     61     FROST_hash_point_update (&hash_state,
     62                              &commitments[i].hiding_commitment);
     63     FROST_hash_point_update (&hash_state,
     64                              &commitments[i].binding_commitment);
     65   }
     66 
     67   struct FROST_HashCode group_commitments_hash;
     68   FROST_hash_final (&hash_state, &group_commitments_hash);
     69 
     70   // 2. H(identifier || message || group_commitment_hash)
     71   for (uint8_t i = 0; i < commitments_len; i++)
     72   {
     73     struct FROST_HashState state;
     74     FROST_hash_init (&state);
     75 
     76     FROST_hash_uint8_update (&state, commitments[i].identifier);
     77     FROST_hash_hash_update (&state, &mh->hash);
     78     FROST_hash_hash_update (&state, &group_commitments_hash);
     79 
     80     struct FROST_HashCode rho_input;
     81     FROST_hash_final (&state, &rho_input);
     82 
     83     FROST_hash_to_scalar (&binding_factors[i].binding_factor, &rho_input);
     84 
     85     // Set index
     86     binding_factors[i].identifier = commitments[i].identifier;
     87   }
     88 }
     89 
     90 /**
     91  * Returns the binding factor of a specific participant.
     92  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-list-operations
     93 */
     94 enum GNUNET_GenericReturnValue
     95 FROST_binding_factor_for_participant_ (
     96   struct FROST_BindingFactor *binding_factor,
     97   const struct FROST_BindingFactor binding_factors[],
     98   uint8_t binding_factors_len,
     99   uint8_t participant)
    100 {
    101   for (uint8_t i = 0; i < binding_factors_len; i++)
    102   {
    103     if (participant == binding_factors[i].identifier)
    104     {
    105       FROST_scalar_copy_to (&binding_factor->binding_factor,
    106                             &binding_factors[i].binding_factor);
    107       binding_factor->identifier = binding_factors[i].identifier;
    108       return GNUNET_OK;
    109     }
    110   }
    111   return GNUNET_NO;     // invalid participant
    112 }
    113 
    114 /**
    115  * Computes the group commitment.
    116  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-group-commitment-computatio
    117  *
    118 */
    119 void
    120 FROST_compute_group_commitment_ (
    121   struct FROST_GroupCommitment *group_commitment,
    122   const struct FROST_Commitment commitments[],
    123   const struct FROST_BindingFactor
    124   binding_factors[],
    125   uint8_t comm_and_bind_len)
    126 {
    127   // Set group commitment to the identity element
    128   FROST_point_identity (&group_commitment->commitment);
    129 
    130   for (uint8_t i = 0; i < comm_and_bind_len; i++)
    131   {
    132     // Get binding factor
    133     struct FROST_BindingFactor binding_factor;
    134     FROST_binding_factor_for_participant_ (&binding_factor, binding_factors,
    135                                            comm_and_bind_len,
    136                                            binding_factors[i].identifier);
    137 
    138     // scalarmult binding_nonce_commitment, binding_factor
    139     struct FROST_Point binding_nonce;
    140     FROST_point_mul_scalar (&binding_nonce,
    141                             &commitments[i].binding_commitment,
    142                             &binding_factor.binding_factor);
    143 
    144     // Point add hiding_nonce_commitment with binding_nonce
    145     struct FROST_Point hiding_nonce;
    146     FROST_point_add_point (&hiding_nonce, &commitments[i].hiding_commitment,
    147                            &binding_nonce);
    148 
    149     // Point add group_commitment, ^
    150     FROST_point_add_point (&group_commitment->commitment,
    151                            &group_commitment->commitment, &hiding_nonce);
    152   }
    153 }
    154 
    155 /**
    156  * Computes the lagrange coefficient for a specific participant.
    157  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-polynomials
    158  *
    159 */
    160 enum GNUNET_GenericReturnValue
    161 FROST_compute_lagrange_coefficient_ (
    162   struct FROST_Coefficient *coefficient,
    163   uint8_t participant,
    164   const struct FROST_Commitment commitments[],
    165   size_t commitments_len)
    166 {
    167   uint8_t indices[commitments_len];
    168   participants_from_commitment_list (indices, commitments, commitments_len);
    169 
    170   // validate inputs -> invalid parameters
    171   if (0 == participant)    // own id is NOT 0
    172     return GNUNET_NO;
    173 
    174   int id_in_indices = 0;
    175 
    176   for (uint8_t i = 0; i < commitments_len; i++)
    177   {
    178     if (0 == indices[i])    // no other id is 0
    179       return GNUNET_NO;
    180 
    181     if (participant == indices[i])
    182       id_in_indices++;
    183   }
    184 
    185   if (1 != id_in_indices) // own id exists exactly 1 time
    186     return GNUNET_NO;
    187 
    188   // x-coordinate (id) as 32-byte unsigned char array
    189   struct FROST_Scalar xi;
    190   FROST_scalar_set_uint8 (&xi, participant);
    191 
    192   // Initialize numerator and denominator to '1' and as 32-byte unsigned char
    193   // array
    194   struct FROST_Scalar num;
    195   struct FROST_Scalar den;
    196   FROST_scalar_one (&num);
    197   FROST_scalar_one (&den);
    198 
    199   // Coefficient = num / den = prod(j - 0) / prod(j - i) \ j = i
    200   for (uint8_t j = 0; j < commitments_len; j++)
    201   {
    202 
    203     // If j == i, do nothing!
    204     if (indices[j] != participant)
    205     {
    206       // x-coordinate of 'j' as 32-byte unsigned char array
    207       struct FROST_Scalar xj;
    208       FROST_scalar_set_uint8 (&xj, indices[j]);
    209 
    210       // num *= (j - 0) = j
    211       FROST_scalar_mul_scalar (&num, &num, &xj);
    212 
    213       // den *= (j - i)
    214       struct FROST_Scalar den_temp;
    215       FROST_scalar_sub_scalar (&den_temp, &xj, &xi);
    216       FROST_scalar_mul_scalar (&den, &den, &den_temp);
    217     }
    218   }
    219 
    220   // coeff = num / den = num * inv(den)
    221   struct FROST_Scalar den_inv;
    222   FROST_scalar_invert (&den_inv, &den);
    223   FROST_scalar_mul_scalar (&coefficient->coeff, &num, &den_inv);
    224 
    225   return GNUNET_OK;
    226 }
    227 
    228 /**
    229  * Computes the signature challenge
    230  * Pseudo code of this function: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-12.html#name-signature-challenge-computa
    231 */
    232 void
    233 FROST_compute_challenge_ (
    234   struct FROST_Challenge *challenge,
    235   const struct FROST_GroupCommitment *group_commitment,
    236   const struct FROST_PublicKey *group_pk,
    237   const struct FROST_MessageHash *mh)
    238 {
    239   struct FROST_HashState hash_state;
    240   FROST_hash_init (&hash_state);
    241 
    242   FROST_hash_point_update (&hash_state, &group_commitment->commitment);
    243   FROST_hash_point_update (&hash_state, &group_pk->pk);
    244   FROST_hash_hash_update (&hash_state, &mh->hash);
    245 
    246   struct FROST_HashCode challenge_hash;
    247   FROST_hash_final (&hash_state, &challenge_hash);
    248 
    249   FROST_hash_to_scalar (&challenge->challenge, &challenge_hash);
    250 
    251   return;
    252 }