frost_high.h (11192B)
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 include/frost_high.h 18 * @brief frosix high level api to create a signature share 19 * @author Joel Urech 20 */ 21 #ifndef FROST_HIGH_H 22 #define FROST_HIGH_H 23 24 #include "frost_low.h" 25 #include <gnunet/gnunet_util_lib.h> 26 27 /** 28 * Representation of the PUBLIC KEY 29 */ 30 struct FROST_PublicKey 31 { 32 /** 33 * Our public key is an element on the elliptic curve. 34 */ 35 struct FROST_Point pk; 36 }; 37 38 /** 39 * Representation of the KEY MATERIAL every participant needs in order to 40 * create a partial signature. 41 * Gets generated in a key generation process. 42 */ 43 struct FROST_KeyPair 44 { 45 /** 46 * Unique identifier of the participant, must be greater than 0 and less 47 * than 255. 48 */ 49 uint8_t identifier; 50 /** 51 * The secret key of the participant, a scalar in the range of the elliptic 52 * curve. 53 */ 54 struct FROST_Scalar my_sk; 55 /** 56 * Public key matching the secret key above, as an element on the elliptic 57 * curve. 58 */ 59 struct FROST_Point my_pk; 60 /** 61 * Public key to identify the group and to verify the final signatures. 62 */ 63 struct FROST_PublicKey group_pk; 64 }; 65 66 /** 67 * Representation of a HASH over an arbitrary long message. 68 */ 69 struct FROST_MessageHash 70 { 71 /** 72 * The hash of our message. 73 */ 74 struct FROST_HashCode hash; 75 }; 76 77 /** 78 * Representation of a NONCE generated by each participant in 'Round 1'. 79 */ 80 struct FROST_Nonce 81 { 82 /** 83 * Secret hiding or blinding value, a random scalar in the range of the elliptic 84 * curve. 85 */ 86 struct FROST_Scalar hiding_nonce; 87 /** 88 * Secret binding value, a random scalar in the range of the elliptic curve. 89 */ 90 struct FROST_Scalar binding_nonce; 91 }; 92 93 /** 94 * Representation of a COMMITMENT generated by each participant in 'Round 1'. 95 */ 96 struct FROST_Commitment 97 { 98 /** 99 * ID of the participant issuing the commitment. 100 */ 101 uint8_t identifier; 102 /** 103 * Public hiding or blinding value, an element on the elliptic curve. 104 */ 105 struct FROST_Point hiding_commitment; 106 /** 107 * Public binding value, an element on the elliptic curve. 108 */ 109 struct FROST_Point binding_commitment; 110 }; 111 112 /** 113 * Representation of a PARTIAL SIGNATURE. 114 */ 115 struct FROST_SignatureShare 116 { 117 /** 118 * Not sure if needed... 119 */ 120 uint8_t identifier; 121 /** 122 * The resulting signature share, a scalar in the range of the elliptic 123 * curve. 124 */ 125 struct FROST_Scalar sig_share; 126 /** 127 * The partial public key for convenience only. 128 * Otherwise the 'SA' has to compute each partial public key to verify the 129 * partial signature. 130 */ 131 struct FROST_Point pk_i; 132 }; 133 134 135 /** 136 * Representation of a Schnorr SIGNATURE 137 */ 138 struct FROST_Signature 139 { 140 /** 141 * The 'R' value aka group commitment, as an element on the elliptic curve. 142 */ 143 struct FROST_Point r; 144 /** 145 * The aggregation of all partial signatures, a scalar in the range of the 146 * elliptic curve. 147 * This is the 's' value in a EdDSA signature scheme. 148 */ 149 struct FROST_Scalar z; 150 }; 151 152 153 /** 154 * High entropy value to seed the nonce generation function. 155 * If this value gets reused, an attack on the private key is possible! 156 */ 157 struct FROST_CommitmentSeed 158 { 159 /** 160 * The seed is instantiated as a random scalar value from the group. 161 */ 162 struct FROST_Scalar scal; 163 }; 164 165 /** 166 * Initializes the underlying libsodium library.Always call this function 167 * first, before using libfrost! 168 * 169 * @result Returns 0 on success, -1 on failure and 1 if the library had already 170 * been initialized. 171 */ 172 int 173 FROST_init (void); 174 175 /** 176 * @brief Before a user can start a signing process, he has to convert a message, 177 * an arbitrary amount of data, into a hash value that we can use. 178 * 179 * @param[out] message_hash The resulting hash 180 * @param[in] msg The real message, a pointer to an abritrary long datablock 181 * @param msg_len Nmber of bytes, the length, of the given datablock 182 */ 183 void 184 FROST_message_to_hash (struct FROST_MessageHash *message_hash, 185 const void *msg, 186 size_t msg_len); 187 188 189 /** 190 * Generates a high entropy and unpredictable random value 191 * in the range of [0..L[. * L is the order of the ristretto255 group. 192 * Take care if application runs as a VM, can produce same output if 193 * snapshotted and restored! 194 * 195 * @param[out] seed The returning random and therefore unpredictable bytes. 196 */ 197 void 198 FROST_get_random_seed (struct FROST_CommitmentSeed *seed); 199 200 /** 201 * @brief The Signature Aggregator 'SA' (normally the user) chooses 't' (t = threshold) random participants 202 * out of all available participants and asks them to send him a commitment. 203 * This function generates a secret nonce- and a public commitment value. 204 * 205 * @param[out] nonce The resulting secret nonce, which we will use in 'Round 2' 206 * @param[out] commitment The resulting public commitment, which we send back to the 'SA' 207 * @param[in] message_hash Hash of the message to sign. Is part of the commitment 208 * @param[in] seed A high entropy random seed to generate the commitment from. 209 * DO NOT USE TWICE! 210 */ 211 void 212 FROST_generate_nonce_and_commitment (struct FROST_Nonce *nonce, 213 struct FROST_Commitment *commitment, 214 const struct 215 FROST_MessageHash *message_hash, 216 const struct FROST_CommitmentSeed *seed); 217 218 /** 219 * @brief The 'SA' constructs a sorted list out of all commitments and send this commitment list together with the message hash to each chosen participant. 220 * Every participant has to verify for each of the received commitments if they are actually two valid encoded points on the curve. 221 * If the validation fails, abort the signature process and return to the 'SA' which of the commitment has failed. 222 * 223 * @param[in] commitment A single commitment to validate 224 * @return GNUNET_OK if everything is ok, otherwise GNUNET_NO. Abort the signing process in case its not 1! 225 */ 226 enum GNUNET_GenericReturnValue 227 FROST_validate_commitment ( 228 const struct FROST_Commitment *commitment); 229 230 231 /** 232 * @brief If the validation has not failed, compute a signature share for the given message hash. 233 * 234 * Secret key share of participant: \f$s_i\f$ 235 * Nonce of participant: \f$(d_i, e_i)\f$ 236 * Lagrange coefficient of participant: \f$\lambda_i\f$ 237 * Compute binding value of each participant: 238 * \f$p_i = H(i || m || B)\f$ 239 * Compute group commitment: 240 * \f$R_i = D_i(E_i)^{p_i}\f$ 241 * \f$R = \prod R_i\f$ 242 * Compute challenge: 243 * \f$c = H(R || pk || m)\f$ 244 * Compute signature share: 245 * \f$z_i = d_i + (e_i \cdot p_i)\lambda_is_ic\f$ 246 * 247 * @param[out] signature_share The resulting signature share. We have to return this data back to the 'SA' (\f$(z_i,pk_i)\f$) 248 * @param[in] message_hash Our message we want to sign (\f$m\f$) 249 * @param[in] commitments List of all commitments, the order of the elements is crucial! (\f$B\f$) 250 * @param commitments_len Number of commitments, usually corresponds to the number of participants 251 * @param my_key_pair Our key material, which was generated by a preliminary key generation process 252 * @param my_nonce Our secret random value, matching our commitment that we sent previously to the 'SA' 253 * @return #GNUNET_OK 254 * #GNUNET_NO 255 */ 256 enum GNUNET_GenericReturnValue 257 FROST_sign_message_hash (struct FROST_SignatureShare *signature_share, 258 const struct FROST_MessageHash *message_hash, 259 const struct FROST_Commitment commitments[], 260 size_t commitments_len, 261 const struct FROST_KeyPair *my_key_pair, 262 const struct FROST_Nonce *my_nonce); 263 264 /** 265 * @brief Gives the 'SA' the possibility to verify each received signature share 266 * against the commitment from round 1. 267 * 268 * Compute binding value of each participant: 269 * \f$p_i = H(i || m || B)\f$ 270 * Compute group commitment: 271 * \f$R_i = D_i(E_i)^{p_i}\f$ 272 * \f$R = \prod R_i\f$ 273 * Compute challenge: 274 * \f$c = H(R || pk || m)\f$ 275 * Lagrange coefficient of participant: \f$\lambda_i\f$ 276 * Verify signature share: 277 * \f$g^{z_i} = R_ipk^{c\lambda_i}\f$ ? 278 * 279 * @param[in] commitment_i The commitment that the participant 'i' has previously sent (\f$(D_i, E_i)\f$) 280 * @param[in] signature_share_i The partial signature of the participant 'i' to be verified (\f$z_i\f$) 281 * @param[in] commitments List of all commitments. The order of the elements is crucial! (\f$B\f$) 282 * @param commitments_len Number of commitments, usually corresponds to the number of participants 283 * @param[in] public_key Group public key is needed to compute the group challenge (\f$pk\f$) 284 * @param[in] message_hash The hashed message (\f$m\f$) 285 * @return GNUNET_OK or GNUNET_NO. Abort the signing process in case its not GNUNET_OK! 286 */ 287 enum GNUNET_GenericReturnValue 288 FROST_verify_signature_share (const struct FROST_Commitment *commitment_i, 289 const struct FROST_SignatureShare 290 *signature_share_i, 291 const struct FROST_Commitment commitments[], 292 uint8_t commitments_len, 293 const struct FROST_PublicKey *public_key, 294 const struct FROST_MessageHash *message_hash); 295 296 /** 297 * @brief Aggregates the signature shares from all participants, computes the group commitment aka 'R' value 298 * and returns the final signature over the given message. 299 * Sum all singature shares: 300 * \f$z = \sum z_i\f$ 301 * Compute binding value of each participant: 302 * \f$p_i = H(i || m || B)\f$ 303 * Compute group commitment: 304 * \f$R_i = D_i(E_i)^{p_i}\f$ 305 * \f$R = \prod R_i\f$ 306 * Resulting signature: 307 * \f$sig = (R, z)\f$ 308 * 309 * @param[out] signature The resulting signature of the given message (\f$sig = (R, z)\f$) 310 * @param[in] commitments List of all commitments. The order of the elements is crucial! (\f$B\f$) 311 * @param[in] signature_shares List of all partial signatures. The sorting doesn't matter (\f$z_i\f$) 312 * @param commitments_and_sig_shares_len Should correspond to the number of participants 313 * @param[in] message_hash The hashed message as an element on the elliptic curve (\f$m\f$) 314 */ 315 void 316 FROST_compose_signature (struct FROST_Signature *signature, 317 const struct FROST_Commitment commitments[], 318 const struct FROST_SignatureShare 319 signature_shares[], 320 uint8_t commitments_and_sig_shares_len, 321 const struct FROST_MessageHash *message_hash); 322 323 #endif