diff options
author | Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch> | 2021-12-06 22:13:35 +0100 |
---|---|---|
committer | Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch> | 2021-12-07 20:44:33 +0100 |
commit | 2bcdfc2f958f5fd2512103c2240f1c24c07524d7 (patch) | |
tree | 3e96bd0ccf4e21ca44e0e82beaf7f604213e38c4 /src | |
parent | fa483f6cbce4873defe81234f44808bb8042fa68 (diff) | |
download | gnunet-2bcdfc2f958f5fd2512103c2240f1c24c07524d7.tar.gz gnunet-2bcdfc2f958f5fd2512103c2240f1c24c07524d7.zip |
add crypto_cs implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 270 | ||||
-rw-r--r-- | src/util/Makefile.am | 1 | ||||
-rw-r--r-- | src/util/crypto_cs.c | 425 |
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 | */ | ||
398 | struct 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 | */ | ||
410 | struct 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 | */ | ||
423 | struct GNUNET_CRYPTO_CsPrivateKey | ||
424 | { | ||
425 | struct GNUNET_CRYPTO_Cs25519Scalar scalar; | ||
426 | }; | ||
427 | |||
428 | |||
429 | /** | ||
430 | * The public information of an Schnorr key pair. | ||
431 | */ | ||
432 | struct GNUNET_CRYPTO_CsPublicKey | ||
433 | { | ||
434 | struct GNUNET_CRYPTO_Cs25519Point point; | ||
435 | }; | ||
436 | |||
437 | |||
438 | /** | ||
439 | * Secret used for blinding (alpha and beta). | ||
440 | */ | ||
441 | struct 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 | */ | ||
451 | struct 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 | */ | ||
460 | struct GNUNET_CRYPTO_CsRPublic | ||
461 | { | ||
462 | struct GNUNET_CRYPTO_Cs25519Point point; | ||
463 | }; | ||
464 | |||
465 | |||
466 | /** | ||
467 | * Schnorr c to be signed | ||
468 | */ | ||
469 | struct GNUNET_CRYPTO_CsC | ||
470 | { | ||
471 | struct GNUNET_CRYPTO_Cs25519Scalar scalar; | ||
472 | }; | ||
473 | |||
474 | |||
475 | /** | ||
476 | * s in the signature | ||
477 | */ | ||
478 | struct GNUNET_CRYPTO_CsS | ||
479 | { | ||
480 | struct GNUNET_CRYPTO_Cs25519Scalar scalar; | ||
481 | }; | ||
482 | |||
483 | |||
484 | /** | ||
485 | * blinded s in the signature | ||
486 | */ | ||
487 | struct GNUNET_CRYPTO_CsBlindS | ||
488 | { | ||
489 | struct GNUNET_CRYPTO_Cs25519Scalar scalar; | ||
490 | }; | ||
491 | |||
492 | |||
493 | /** | ||
494 | * CS Signtature containing scalar s and point R | ||
495 | */ | ||
496 | struct 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 | */ | ||
509 | struct 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 | */ | ||
2565 | void | ||
2566 | GNUNET_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 | */ | ||
2575 | void | ||
2576 | GNUNET_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 | */ | ||
2593 | void | ||
2594 | GNUNET_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 | */ | ||
2605 | void | ||
2606 | GNUNET_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 | */ | ||
2621 | void | ||
2622 | GNUNET_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 | */ | ||
2640 | void | ||
2641 | GNUNET_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 | */ | ||
2668 | unsigned int | ||
2669 | GNUNET_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 | */ | ||
2685 | void | ||
2686 | GNUNET_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 | */ | ||
2702 | enum GNUNET_GenericReturnValue | ||
2703 | GNUNET_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 | */ | ||
48 | void | ||
49 | GNUNET_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 | */ | ||
61 | void | ||
62 | GNUNET_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 | */ | ||
76 | static void | ||
77 | map_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 | */ | ||
98 | void | ||
99 | GNUNET_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 | */ | ||
129 | void | ||
130 | GNUNET_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 | */ | ||
149 | void | ||
150 | GNUNET_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 | /* | ||
176 | order of subgroup required for scalars by libsodium | ||
177 | 2^252 + 27742317777372353535851937790883648493 | ||
178 | copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c | ||
179 | and converted to big endian | ||
180 | */ | ||
181 | static 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 | */ | ||
195 | static void | ||
196 | cs_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 | */ | ||
242 | static void | ||
243 | calc_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 | */ | ||
281 | void | ||
282 | GNUNET_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 | */ | ||
328 | unsigned int | ||
329 | GNUNET_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 | */ | ||
375 | void | ||
376 | GNUNET_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 | */ | ||
397 | enum GNUNET_GenericReturnValue | ||
398 | GNUNET_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 | } | ||