crypto_implementation.tex (9413B)
1 \begin{lstlisting}[style=bfh-c,language=C,, caption={Crypto Implementation API}, label={lst:cryptoapi}] 2 #include <sodium.h> 3 4 /** 5 * IMPLEMENTATION NOTICE: 6 * 7 * This is an implementation of the Schnorr, Blind Schnorr and 8 * Clause Blind Schnorr Signature Scheme using Curve25519. 9 * We use libsodium wherever possible. 10 * 11 * Blind Schnorr: The Blind Schnorr Signature Scheme is BROKEN! 12 * Use the Clause Blind Schnorr Signature Scheme instead. 13 * 14 * Clause Blind Schnorr Signature Scheme: 15 * This is a variation of the Blind Schnorr Signature Scheme where all operations 16 * before the signature creation are performed twice. 17 * The signer randomly chooses one of the two sessions and only creates the signature for this session. 18 * Note that the Clause part needs to be implemented by whoever uses this API. 19 * Further details about the Clause Blind Schnorr Signature Scheme can be found here: 20 * https://eprint.iacr.org/2019/877.pdf 21 */ 22 23 24 /** 25 * Curve25519 Scalar 26 */ 27 struct GNUNET_CRYPTO_Cs25519Scalar 28 { 29 /** 30 * 32 byte scalar 31 */ 32 unsigned char d[crypto_core_ed25519_SCALARBYTES]; 33 }; 34 35 36 /** 37 * Curve25519 point 38 */ 39 struct GNUNET_CRYPTO_Cs25519Point 40 { 41 /** 42 * This is a point on the Curve25519. 43 * The x coordinate can be restored using the y coordinate 44 */ 45 unsigned char y[crypto_core_ed25519_BYTES]; 46 }; 47 48 49 /** 50 * The private information of an Schnorr key pair. 51 */ 52 struct GNUNET_CRYPTO_CsPrivateKey 53 { 54 struct GNUNET_CRYPTO_Cs25519Scalar scalar; 55 }; 56 57 58 /** 59 * The public information of an Schnorr key pair. 60 */ 61 struct GNUNET_CRYPTO_CsPublicKey 62 { 63 struct GNUNET_CRYPTO_Cs25519Point point; 64 }; 65 66 67 /** 68 * Secret used for blinding (alpha and beta). 69 */ 70 struct GNUNET_CRYPTO_CsBlindingSecret 71 { 72 struct GNUNET_CRYPTO_Cs25519Scalar alpha; 73 struct GNUNET_CRYPTO_Cs25519Scalar beta; 74 }; 75 76 77 /** 78 * the private r used in the signature 79 */ 80 struct GNUNET_CRYPTO_CsRSecret 81 { 82 struct GNUNET_CRYPTO_Cs25519Scalar scalar; 83 }; 84 85 86 /** 87 * the public R (derived from r) used in c 88 */ 89 struct GNUNET_CRYPTO_CsRPublic 90 { 91 struct GNUNET_CRYPTO_Cs25519Point point; 92 }; 93 94 /** 95 * Schnorr c to be signed 96 */ 97 struct GNUNET_CRYPTO_CsC 98 { 99 struct GNUNET_CRYPTO_Cs25519Scalar scalar; 100 }; 101 102 /** 103 * s in the signature 104 */ 105 struct GNUNET_CRYPTO_CsS 106 { 107 struct GNUNET_CRYPTO_Cs25519Scalar scalar; 108 }; 109 110 /** 111 * blinded s in the signature 112 */ 113 struct GNUNET_CRYPTO_CsBlindS 114 { 115 struct GNUNET_CRYPTO_Cs25519Scalar scalar; 116 }; 117 118 /** 119 * CS Signtature containing scalar s and point R 120 */ 121 struct GNUNET_CRYPTO_CsSignature 122 { 123 /** 124 * Schnorr signatures are composed of a scalar s and a curve point 125 */ 126 struct GNUNET_CRYPTO_CsS s_scalar; 127 struct GNUNET_CRYPTO_Cs25519Point r_point; 128 }; 129 130 /** 131 * Nonce 132 */ 133 struct GNUNET_CRYPTO_CsNonce 134 { 135 /*a nonce*/ 136 unsigned char nonce[256 / 8]; 137 }; 138 139 140 /** 141 * Create a new random private key. 142 * 143 * @param[out] priv where to write the fresh private key 144 */ 145 void 146 GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv); 147 148 149 /** 150 * Extract the public key of the given private key. 151 * 152 * @param priv the private key 153 * @param[out] pub where to write the public key 154 */ 155 void 156 GNUNET_CRYPTO_cs_private_key_get_public (const struct GNUNET_CRYPTO_CsPrivateKey *priv, 157 struct GNUNET_CRYPTO_CsPublicKey *pub); 158 159 160 /** 161 * Derive a new secret r pair r0 and r1. 162 * In original papers r is generated randomly 163 * To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE 164 * To ensure unpredictability a new nonce should be used when a new r needs to be derived. 165 * Uses HKDF internally. 166 * Comment: Can be done in one HKDF shot and split output. 167 * 168 * @param nonce is a random nonce 169 * @param lts is a long-term-secret in form of a private key 170 * @param[out] r array containing derived secrets r0 and r1 171 */ 172 void 173 GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce, 174 const struct GNUNET_CRYPTO_CsPrivateKey *lts, 175 struct GNUNET_CRYPTO_CsRSecret r[2]); 176 177 178 /** 179 * Extract the public R of the given secret r. 180 * 181 * @param r_priv the private key 182 * @param[out] r_pub where to write the public key 183 */ 184 void 185 GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv, 186 struct GNUNET_CRYPTO_CsRPublic *r_pub); 187 188 189 /** 190 * Derives new random blinding factors. 191 * In original papers blinding factors are generated randomly 192 * To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE 193 * To ensure unpredictability a new nonce has to be used. 194 * Uses HKDF internally 195 * 196 * @param secret is secret to derive blinding factors 197 * @param secret_len secret length 198 * @param[out] bs array containing the two derivedGNUNET_CRYPTO_CsBlindingSecret 199 */ 200 void 201 GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct GNUNET_CRYPTO_CsNonce *blind_seed, 202 struct GNUNET_CRYPTO_CsBlindingSecret bs[2]); 203 204 205 /** 206 * Calculate two blinded c's 207 * Comment: One would be insecure due to Wagner's algorithm solving ROS 208 * 209 * @param bs array of the two blinding factor structs each containing alpha and beta 210 * @param r_pub array of the two signer's nonce R 211 * @param pub the public key of the signer 212 * @param msg the message to blind in preparation for signing 213 * @param msg_len length of message msg 214 * @param[out] blinded_c array of the two blinded c's 215 */ 216 void 217 GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2], 218 const struct GNUNET_CRYPTO_CsRPublic r_pub[2], 219 const struct GNUNET_CRYPTO_CsPublicKey *pub, 220 const void *msg, 221 size_t msg_len, 222 struct GNUNET_CRYPTO_CsC blinded_c[2]); 223 224 225 /** 226 * Sign a blinded c 227 * This function derives b from a nonce and a longterm secret 228 * In original papers b is generated randomly 229 * To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE. 230 * To ensure unpredictability a new nonce has to be used for every signature 231 * HKDF is used internally for derivation 232 * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive 233 * 234 * @param priv private key to use for the signing and as LTS in HKDF 235 * @param r array of the two secret nonce from the signer 236 * @param c array of the two blinded c to sign c_b 237 * @param nonce is a random nonce 238 * @param[out] blinded_signature_scalar where to write the signature 239 * @return 0 or 1 for b (see Clause Blind Signature Scheme) 240 */ 241 int 242 GNUNET_CRYPTO_cs_sign_derive(const struct GNUNET_CRYPTO_CsPrivateKey *priv, 243 const struct GNUNET_CRYPTO_CsRSecret r[2], 244 const struct GNUNET_CRYPTO_CsC c[2], 245 const struct GNUNET_CRYPTO_CsNonce *nonce, 246 struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar 247 ); 248 249 250 /** 251 * Unblind a blind-signed signature using a c that was blinded 252 * 253 * @param blinded_signature_scalar the signature made on the blinded c 254 * @param bs the blinding factors used in the blinding 255 * @param[out] signature_scalar where to write the unblinded signature 256 */ 257 void 258 GNUNET_CRYPTO_cs_unblind (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, 259 const struct GNUNET_CRYPTO_CsBlindingSecret *bs, 260 struct GNUNET_CRYPTO_CsS *signature_scalar); 261 262 263 /** 264 * Verify whether the given message corresponds to the given signature and the 265 * signature is valid with respect to the given public key. 266 * 267 * @param sig signature that is being validated 268 * @param pub public key of the signer 269 * @param msg is the message that should be signed by @a sig (message is used to calculate c) 270 * @param msg_len is the message length 271 * @returns #GNUNET_YES on success, #GNUNET_SYSERR if key parameter(s) invalid #GNUNET_NO if signature invalid 272 */ 273 enum GNUNET_GenericReturnValue 274 GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig, 275 const struct GNUNET_CRYPTO_CsPublicKey *pub, 276 const void *msg, 277 size_t msg_len); 278 279 \end{lstlisting}