aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>2021-12-06 22:13:35 +0100
committerLucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>2021-12-07 20:44:33 +0100
commit2bcdfc2f958f5fd2512103c2240f1c24c07524d7 (patch)
tree3e96bd0ccf4e21ca44e0e82beaf7f604213e38c4 /src
parentfa483f6cbce4873defe81234f44808bb8042fa68 (diff)
downloadgnunet-2bcdfc2f958f5fd2512103c2240f1c24c07524d7.tar.gz
gnunet-2bcdfc2f958f5fd2512103c2240f1c24c07524d7.zip
add crypto_cs implementation
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_crypto_lib.h270
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_cs.c425
3 files changed, 696 insertions, 0 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index edb4bb230..9166f822b 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -392,6 +392,127 @@ struct GNUNET_CRYPTO_PaillierCiphertext
392}; 392};
393 393
394 394
395/**
396 * Curve25519 Scalar
397 */
398struct GNUNET_CRYPTO_Cs25519Scalar
399{
400 /**
401 * 32 byte scalar
402 */
403 unsigned char d[crypto_core_ed25519_SCALARBYTES];
404};
405
406
407/**
408 * Curve25519 point
409 */
410struct GNUNET_CRYPTO_Cs25519Point
411{
412 /**
413 * This is a point on the Curve25519.
414 * The x coordinate can be restored using the y coordinate
415 */
416 unsigned char y[crypto_core_ed25519_BYTES];
417};
418
419
420/**
421 * The private information of an Schnorr key pair.
422 */
423struct GNUNET_CRYPTO_CsPrivateKey
424{
425 struct GNUNET_CRYPTO_Cs25519Scalar scalar;
426};
427
428
429/**
430 * The public information of an Schnorr key pair.
431 */
432struct GNUNET_CRYPTO_CsPublicKey
433{
434 struct GNUNET_CRYPTO_Cs25519Point point;
435};
436
437
438/**
439 * Secret used for blinding (alpha and beta).
440 */
441struct GNUNET_CRYPTO_CsBlindingSecret
442{
443 struct GNUNET_CRYPTO_Cs25519Scalar alpha;
444 struct GNUNET_CRYPTO_Cs25519Scalar beta;
445};
446
447
448/**
449 * the private r used in the signature
450 */
451struct GNUNET_CRYPTO_CsRSecret
452{
453 struct GNUNET_CRYPTO_Cs25519Scalar scalar;
454};
455
456
457/**
458 * the public R (derived from r) used in c
459 */
460struct GNUNET_CRYPTO_CsRPublic
461{
462 struct GNUNET_CRYPTO_Cs25519Point point;
463};
464
465
466/**
467 * Schnorr c to be signed
468 */
469struct GNUNET_CRYPTO_CsC
470{
471 struct GNUNET_CRYPTO_Cs25519Scalar scalar;
472};
473
474
475/**
476 * s in the signature
477 */
478struct GNUNET_CRYPTO_CsS
479{
480 struct GNUNET_CRYPTO_Cs25519Scalar scalar;
481};
482
483
484/**
485 * blinded s in the signature
486 */
487struct GNUNET_CRYPTO_CsBlindS
488{
489 struct GNUNET_CRYPTO_Cs25519Scalar scalar;
490};
491
492
493/**
494 * CS Signtature containing scalar s and point R
495 */
496struct GNUNET_CRYPTO_CsSignature
497{
498 /**
499 * Schnorr signatures are composed of a scalar s and a curve point
500 */
501 struct GNUNET_CRYPTO_CsS s_scalar;
502 struct GNUNET_CRYPTO_CsRPublic r_point;
503};
504
505
506/**
507 * Nonce
508 */
509struct GNUNET_CRYPTO_CsNonce
510{
511 /*a nonce*/
512 unsigned char nonce[256 / 8];
513};
514
515
395/* **************** Functions and Macros ************* */ 516/* **************** Functions and Macros ************* */
396 517
397/** 518/**
@@ -2436,6 +2557,155 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
2436 const struct GNUNET_CRYPTO_RsaPublicKey *public_key); 2557 const struct GNUNET_CRYPTO_RsaPublicKey *public_key);
2437 2558
2438 2559
2560/**
2561 * Create a new random private key.
2562 *
2563 * @param[out] priv where to write the fresh private key
2564 */
2565void
2566GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv);
2567
2568
2569/**
2570 * Extract the public key of the given private key.
2571 *
2572 * @param priv the private key
2573 * @param[out] pub where to write the public key
2574 */
2575void
2576GNUNET_CRYPTO_cs_private_key_get_public (const struct
2577 GNUNET_CRYPTO_CsPrivateKey *priv,
2578 struct GNUNET_CRYPTO_CsPublicKey *pub);
2579
2580
2581/**
2582 * Derive a new secret r pair r0 and r1.
2583 * In original papers r is generated randomly
2584 * To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE
2585 * To ensure unpredictability a new nonce should be used when a new r needs to be derived.
2586 * Uses HKDF internally.
2587 * Comment: Can be done in one HKDF shot and split output.
2588 *
2589 * @param nonce is a random nonce
2590 * @param lts is a long-term-secret in form of a private key
2591 * @param[out] r array containing derived secrets r0 and r1
2592 */
2593void
2594GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
2595 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
2596 struct GNUNET_CRYPTO_CsRSecret r[2]);
2597
2598
2599/**
2600 * Extract the public R of the given secret r.
2601 *
2602 * @param r_priv the private key
2603 * @param[out] r_pub where to write the public key
2604 */
2605void
2606GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
2607 struct GNUNET_CRYPTO_CsRPublic *r_pub);
2608
2609
2610/**
2611 * Derives new random blinding factors.
2612 * In original papers blinding factors are generated randomly
2613 * To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE
2614 * To ensure unpredictability a new nonce has to be used.
2615 * Uses HKDF internally
2616 *
2617 * @param secret is secret to derive blinding factors
2618 * @param secret_len secret length
2619 * @param[out] bs array containing the two derived blinding secrets
2620 */
2621void
2622GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret,
2623 size_t secret_len,
2624 struct GNUNET_CRYPTO_CsBlindingSecret
2625 bs[2]);
2626
2627
2628/**
2629 * Calculate two blinded c's
2630 * Comment: One would be insecure due to Wagner's algorithm solving ROS
2631 *
2632 * @param bs array of the two blinding factor structs each containing alpha and beta
2633 * @param r_pub array of the two signer's nonce R
2634 * @param pub the public key of the signer
2635 * @param msg the message to blind in preparation for signing
2636 * @param msg_len length of message msg
2637 * @param[out] blinded_c array of the two blinded c's
2638 * @param[out] blinded_r_pub array of the two blinded R
2639 */
2640void
2641GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
2642 bs[2],
2643 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
2644 const struct GNUNET_CRYPTO_CsPublicKey *pub,
2645 const void *msg,
2646 size_t msg_len,
2647 struct GNUNET_CRYPTO_CsC blinded_c[2],
2648 struct GNUNET_CRYPTO_CsRPublic
2649 blinded_r_pub[2]);
2650
2651
2652/**
2653 * Sign a blinded c
2654 * This function derives b from a nonce and a longterm secret
2655 * In original papers b is generated randomly
2656 * To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE.
2657 * To ensure unpredictability a new nonce has to be used for every signature
2658 * HKDF is used internally for derivation
2659 * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
2660 *
2661 * @param priv private key to use for the signing and as LTS in HKDF
2662 * @param r array of the two secret nonce from the signer
2663 * @param c array of the two blinded c to sign c_b
2664 * @param nonce is a random nonce
2665 * @param[out] blinded_signature_scalar where to write the signature
2666 * @return 0 or 1 for b (see Clause Blind Signature Scheme)
2667 */
2668unsigned int
2669GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
2670 const struct GNUNET_CRYPTO_CsRSecret r[2],
2671 const struct GNUNET_CRYPTO_CsC c[2],
2672 const struct GNUNET_CRYPTO_CsNonce *nonce,
2673 struct GNUNET_CRYPTO_CsBlindS *
2674 blinded_signature_scalar
2675 );
2676
2677
2678/**
2679 * Unblind a blind-signed signature using a c that was blinded
2680 *
2681 * @param blinded_signature_scalar the signature made on the blinded c
2682 * @param bs the blinding factors used in the blinding
2683 * @param[out] signature_scalar where to write the unblinded signature
2684 */
2685void
2686GNUNET_CRYPTO_cs_unblind (const struct
2687 GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
2688 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
2689 struct GNUNET_CRYPTO_CsS *signature_scalar);
2690
2691
2692/**
2693 * Verify whether the given message corresponds to the given signature and the
2694 * signature is valid with respect to the given public key.
2695 *
2696 * @param sig signature that is being validated
2697 * @param pub public key of the signer
2698 * @param msg is the message that should be signed by @a sig (message is used to calculate c)
2699 * @param msg_len is the message length
2700 * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
2701 */
2702enum GNUNET_GenericReturnValue
2703GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
2704 const struct GNUNET_CRYPTO_CsPublicKey *pub,
2705 const void *msg,
2706 size_t msg_len);
2707
2708
2439#if 0 /* keep Emacsens' auto-indent happy */ 2709#if 0 /* keep Emacsens' auto-indent happy */
2440{ 2710{
2441#endif 2711#endif
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index d21ac5e86..771be1ee3 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -61,6 +61,7 @@ libgnunetutil_la_SOURCES = \
61 container_multihashmap32.c \ 61 container_multihashmap32.c \
62 crypto_symmetric.c \ 62 crypto_symmetric.c \
63 crypto_crc.c \ 63 crypto_crc.c \
64 crypto_cs.c \
64 crypto_ecc.c \ 65 crypto_ecc.c \
65 crypto_ecc_gnsrecord.c \ 66 crypto_ecc_gnsrecord.c \
66 $(DLOG) \ 67 $(DLOG) \
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
new file mode 100644
index 000000000..5c441b669
--- /dev/null
+++ b/src/util/crypto_cs.c
@@ -0,0 +1,425 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014,2016,2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/crypto_cs.c
23 * @brief Clause Blind Schnorr signatures using Curve25519
24 * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
25 * @author Gian Demarmels <gian@demarmels.org>
26 */
27#include "platform.h"
28#include "gnunet_crypto_lib.h"
29#include <sodium.h>
30#include <gcrypt.h>
31
32/**
33 * IMPLEMENTATION NOTICE:
34 *
35 * This is an implementation of the Clause Blind Schnorr Signature Scheme using Curve25519.
36 * Further details about the Clause Blind Schnorr Signature Scheme can be found here:
37 * https://eprint.iacr.org/2019/877.pdf
38 *
39 * We use libsodium wherever possible.
40 */
41
42
43/**
44 * Create a new random private key.
45 *
46 * @param[out] priv where to write the fresh private key
47 */
48void
49GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
50{
51 crypto_core_ed25519_scalar_random (priv->scalar.d);
52}
53
54
55/**
56 * Extract the public key of the given private key.
57 *
58 * @param priv the private key
59 * @param[out] pub where to write the public key
60 */
61void
62GNUNET_CRYPTO_cs_private_key_get_public (const struct
63 GNUNET_CRYPTO_CsPrivateKey *priv,
64 struct GNUNET_CRYPTO_CsPublicKey *pub)
65{
66 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
67 priv->scalar.d));
68}
69
70
71/**
72 * maps 32 random bytes to a scalar
73 * this is necessary because libsodium expects scalar to be in the prime order subgroup
74 * @param[out] scalar containing 32 byte char array, is modified to be in prime order subgroup
75 */
76static void
77map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
78{
79 // perform clamping as described in RFC7748
80 scalar->d[0] &= 248;
81 scalar->d[31] &= 127;
82 scalar->d[31] |= 64;
83}
84
85
86/**
87 * Derive a new secret r pair r0 and r1.
88 * In original papers r is generated randomly
89 * To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE
90 * To ensure unpredictability a new nonce should be used when a new r needs to be derived.
91 * Uses HKDF internally.
92 * Comment: Can be done in one HKDF shot and split output.
93 *
94 * @param nonce is a random nonce
95 * @param lts is a long-term-secret in form of a private key
96 * @param[out] r array containing derived secrets r0 and r1
97 */
98void
99GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
100 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
101 struct GNUNET_CRYPTO_CsRSecret r[2])
102{
103 GNUNET_assert (GNUNET_YES ==
104 GNUNET_CRYPTO_hkdf (r,
105 sizeof (struct GNUNET_CRYPTO_CsRSecret)
106 * 2,
107 GCRY_MD_SHA512,
108 GCRY_MD_SHA256,
109 "r",
110 strlen ("r"),
111 lts,
112 sizeof (*lts),
113 nonce,
114 sizeof (*nonce),
115 NULL,
116 0));
117
118 map_to_scalar_subgroup (&r[0].scalar);
119 map_to_scalar_subgroup (&r[1].scalar);
120}
121
122
123/**
124 * Extract the public R of the given secret r.
125 *
126 * @param r_priv the private key
127 * @param[out] r_pub where to write the public key
128 */
129void
130GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
131 struct GNUNET_CRYPTO_CsRPublic *r_pub)
132{
133 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
134 r_priv->scalar.d));
135}
136
137
138/**
139 * Derives new random blinding factors.
140 * In original papers blinding factors are generated randomly
141 * To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE
142 * To ensure unpredictability a new nonce has to be used.
143 * Uses HKDF internally
144 *
145 * @param secret is secret to derive blinding factors
146 * @param secret_len secret length
147 * @param[out] bs array containing the two derived blinding secrets
148 */
149void
150GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret,
151 size_t secret_len,
152 struct GNUNET_CRYPTO_CsBlindingSecret
153 bs[2])
154{
155 GNUNET_assert (GNUNET_YES ==
156 GNUNET_CRYPTO_hkdf (bs,
157 sizeof (struct
158 GNUNET_CRYPTO_CsBlindingSecret)
159 * 2,
160 GCRY_MD_SHA512,
161 GCRY_MD_SHA256,
162 "alphabeta",
163 strlen ("alphabeta"),
164 secret,
165 secret_len,
166 NULL,
167 0));
168 map_to_scalar_subgroup (&bs[0].alpha);
169 map_to_scalar_subgroup (&bs[0].beta);
170 map_to_scalar_subgroup (&bs[1].alpha);
171 map_to_scalar_subgroup (&bs[1].beta);
172}
173
174
175/*
176order of subgroup required for scalars by libsodium
1772^252 + 27742317777372353535851937790883648493
178copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
179and converted to big endian
180*/
181static const unsigned char L_BIG_ENDIAN[32] = {
182 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
184 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
185};
186
187
188/**
189 * Computes a Hash of (R', m) mapped to a Curve25519 scalar
190 *
191 * @param hash initial hash of the message to be signed
192 * @param pub denomination public key (used as salt)
193 * @param[out] c C containing scalar
194 */
195static void
196cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
197 const void *msg,
198 size_t msg_len,
199 const struct GNUNET_CRYPTO_CsPublicKey *pub,
200 struct GNUNET_CRYPTO_CsC *c)
201{
202 // SHA-512 hash of R' and message
203 size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
204 char r_m_concat[r_m_concat_len];
205 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
206 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
207 struct GNUNET_HashCode prehash;
208 GNUNET_CRYPTO_hash (r_m_concat, r_m_concat_len, &prehash);
209
210 // modulus converted to MPI representation
211 gcry_mpi_t l_mpi;
212 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi, L_BIG_ENDIAN, sizeof(L_BIG_ENDIAN));
213
214 // calculate full domain hash
215 gcry_mpi_t c_mpi;
216 GNUNET_CRYPTO_kdf_mod_mpi (&c_mpi,
217 l_mpi,
218 pub,
219 sizeof(struct GNUNET_CRYPTO_CsPublicKey),
220 &prehash,
221 sizeof(struct GNUNET_HashCode),
222 "Curve25519FDH");
223 gcry_mpi_release (l_mpi);
224
225 // convert c from mpi
226 unsigned char c_big_endian[256 / 8];
227 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian, sizeof(c_big_endian), c_mpi);
228 gcry_mpi_release (c_mpi);
229 for (size_t i = 0; i<32; i++)
230 c->scalar.d[i] = c_big_endian[31 - i];
231}
232
233
234/**
235 * calculate R'
236 *
237 * @param bs blinding secret
238 * @param r_pub R
239 * @param pub public key
240 * @param[out] blinded_r_pub R'
241 */
242static void
243calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
244 const struct GNUNET_CRYPTO_CsRPublic *r_pub,
245 const struct GNUNET_CRYPTO_CsPublicKey *pub,
246 struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
247{
248 // R'i = Ri + alpha i*G + beta i*pub
249 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
250 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
251 alpha_mul_base.y,
252 bs->alpha.d));
253 struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
254 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (beta_mul_pub.y,
255 bs->beta.d,
256 pub->point.y));
257 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
258 GNUNET_assert (0 == crypto_core_ed25519_add (
259 alpha_mul_base_plus_beta_mul_pub.y,
260 alpha_mul_base.y,
261 beta_mul_pub.y));
262 GNUNET_assert (0 == crypto_core_ed25519_add (blinded_r_pub->point.y,
263 r_pub->point.y,
264 alpha_mul_base_plus_beta_mul_pub.
265 y));
266}
267
268
269/**
270 * Calculate two blinded c's
271 * Comment: One would be insecure due to Wagner's algorithm solving ROS
272 *
273 * @param bs array of the two blinding factor structs each containing alpha and beta
274 * @param r_pub array of the two signer's nonce R
275 * @param pub the public key of the signer
276 * @param msg the message to blind in preparation for signing
277 * @param msg_len length of message msg
278 * @param[out] blinded_c array of the two blinded c's
279 * @param[out] blinded_r_pub array of the two blinded R
280 */
281void
282GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
283 bs[2],
284 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
285 const struct GNUNET_CRYPTO_CsPublicKey *pub,
286 const void *msg,
287 size_t msg_len,
288 struct GNUNET_CRYPTO_CsC blinded_c[2],
289 struct GNUNET_CRYPTO_CsRPublic
290 blinded_r_pub[2])
291{
292 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
293 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
294 calc_r_dash (&bs[1], &r_pub[1], pub, &blinded_r_pub[1]);
295
296 // for i 0/1: c'i = H(R'i, msg)
297 struct GNUNET_CRYPTO_CsC c_dash_0;
298 struct GNUNET_CRYPTO_CsC c_dash_1;
299 cs_full_domain_hash (&blinded_r_pub[0], msg, msg_len, pub, &c_dash_0);
300 cs_full_domain_hash (&blinded_r_pub[1], msg, msg_len, pub, &c_dash_1);
301
302 // for i 0/1: ci = c'i + beta i mod p
303 crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
304 c_dash_0.scalar.d,
305 bs[0].beta.d);
306 crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
307 c_dash_1.scalar.d,
308 bs[1].beta.d);
309}
310
311
312/**
313 * Sign a blinded c
314 * This function derives b from a nonce and a longterm secret
315 * In original papers b is generated randomly
316 * To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE.
317 * To ensure unpredictability a new nonce has to be used for every signature
318 * HKDF is used internally for derivation
319 * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
320 *
321 * @param priv private key to use for the signing and as LTS in HKDF
322 * @param r array of the two secret nonce from the signer
323 * @param c array of the two blinded c to sign c_b
324 * @param nonce is a random nonce
325 * @param[out] blinded_signature_scalar where to write the signature
326 * @return 0 or 1 for b (see Clause Blind Signature Scheme)
327 */
328unsigned int
329GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
330 const struct GNUNET_CRYPTO_CsRSecret r[2],
331 const struct GNUNET_CRYPTO_CsC c[2],
332 const struct GNUNET_CRYPTO_CsNonce *nonce,
333 struct GNUNET_CRYPTO_CsBlindS *
334 blinded_signature_scalar
335 )
336{
337 uint32_t hkdf_out;
338
339 // derive clause session identifier b (random bit)
340 GNUNET_assert (GNUNET_YES ==
341 GNUNET_CRYPTO_hkdf (&hkdf_out,
342 sizeof (hkdf_out),
343 GCRY_MD_SHA512,
344 GCRY_MD_SHA256,
345 "b",
346 strlen ("b"),
347 priv,
348 sizeof (*priv),
349 nonce,
350 sizeof (*nonce),
351 NULL,
352 0));
353 unsigned int b = hkdf_out % 2;
354
355 // s = r_b + c_b priv
356 struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
357 crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
358 c[b].scalar.d,
359 priv->scalar.d);
360 crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
361 r[b].scalar.d,
362 c_b_mul_priv.d);
363
364 return b;
365}
366
367
368/**
369 * Unblind a blind-signed signature using a c that was blinded
370 *
371 * @param blinded_signature_scalar the signature made on the blinded c
372 * @param bs the blinding factors used in the blinding
373 * @param[out] signature_scalar where to write the unblinded signature
374 */
375void
376GNUNET_CRYPTO_cs_unblind (const struct
377 GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
378 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
379 struct GNUNET_CRYPTO_CsS *signature_scalar)
380{
381 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
382 blinded_signature_scalar->scalar.d,
383 bs->alpha.d);
384}
385
386
387/**
388 * Verify whether the given message corresponds to the given signature and the
389 * signature is valid with respect to the given public key.
390 *
391 * @param sig signature that is being validated
392 * @param pub public key of the signer
393 * @param msg is the message that should be signed by @a sig (message is used to calculate c)
394 * @param msg_len is the message length
395 * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
396 */
397enum GNUNET_GenericReturnValue
398GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
399 const struct GNUNET_CRYPTO_CsPublicKey *pub,
400 const void *msg,
401 size_t msg_len)
402{
403 // calculate c' = H(R, m)
404 struct GNUNET_CRYPTO_CsC c_dash;
405 cs_full_domain_hash (&sig->r_point, msg, msg_len, pub, &c_dash);
406
407 // s'G ?= R' + c' pub
408 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
409 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
410 sig_scal_mul_base.y,
411 sig->s_scalar.scalar.d));
412 struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
413 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
414 c_dash.scalar.d,
415 pub->point.y));
416 struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
417 GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
418 sig->r_point.point.y,
419 c_dash_mul_pub.y));
420
421 return 0 == GNUNET_memcmp (&sig_scal_mul_base,
422 &R_add_c_dash_mul_pub)
423 ? GNUNET_OK
424 : GNUNET_SYSERR;
425}