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 }