aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2021-12-08 07:57:47 +0100
committert3sserakt <t3ss@posteo.de>2021-12-08 07:58:12 +0100
commitb46bf463d56475edd777cfa7f4209d6fc7c648cd (patch)
tree7b3665c6ff8af603d971a4e85397f3d5f8523609 /src
parent91eec8adabb74b6488a01c45927dfb7c85e1a45e (diff)
parent67b56e366bc73cc9d940721067ae0f3c7f554768 (diff)
downloadgnunet-b46bf463d56475edd777cfa7f4209d6fc7c648cd.tar.gz
gnunet-b46bf463d56475edd777cfa7f4209d6fc7c648cd.zip
Merge branch 'master' of ssh://git.gnunet.org/gnunet
Diffstat (limited to 'src')
-rw-r--r--src/curl/curl.c82
-rw-r--r--src/include/gnunet_crypto_lib.h270
-rw-r--r--src/util/Makefile.am14
-rw-r--r--src/util/crypto_cs.c425
-rw-r--r--src/util/perf_crypto_cs.c185
-rw-r--r--src/util/test_crypto_cs.c533
6 files changed, 1427 insertions, 82 deletions
diff --git a/src/curl/curl.c b/src/curl/curl.c
index 30c2f8c01..684610101 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -858,85 +858,6 @@ GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
858} 858}
859 859
860 860
861#if ENABLE_BENCHMARK
862static void
863do_benchmark (CURLMsg *cmsg)
864{
865 char *url = NULL;
866 double total_as_double = 0;
867 struct GNUNET_TIME_Relative total;
868 struct UrlRequestData *urd;
869 /* Some care required, as curl is using data types (long vs curl_off_t vs
870 * double) inconsistently to store byte count. */
871 curl_off_t size_curl = 0;
872 long size_long = 0;
873 uint64_t bytes_sent = 0;
874 uint64_t bytes_received = 0;
875
876 GNUNET_break (CURLE_OK ==
877 curl_easy_getinfo (cmsg->easy_handle,
878 CURLINFO_TOTAL_TIME,
879 &total_as_double));
880 total.rel_value_us = total_as_double * 1000 * 1000;
881
882 GNUNET_break (CURLE_OK ==
883 curl_easy_getinfo (cmsg->easy_handle,
884 CURLINFO_EFFECTIVE_URL,
885 &url));
886
887 /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total
888 number of bytes received, not clear from curl docs. */
889
890 GNUNET_break (CURLE_OK ==
891 curl_easy_getinfo (cmsg->easy_handle,
892 CURLINFO_HEADER_SIZE,
893 &size_long));
894 bytes_received += size_long;
895
896 GNUNET_break (CURLE_OK ==
897 curl_easy_getinfo (cmsg->easy_handle,
898 CURLINFO_SIZE_DOWNLOAD_T,
899 &size_curl));
900 bytes_received += size_curl;
901
902 /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes
903 sent, again docs are not completely clear. */
904
905 GNUNET_break (CURLE_OK ==
906 curl_easy_getinfo (cmsg->easy_handle,
907 CURLINFO_REQUEST_SIZE,
908 &size_long));
909 bytes_sent += size_long;
910
911 /* We obtain this value to check an invariant, but never use it otherwise. */
912 GNUNET_break (CURLE_OK ==
913 curl_easy_getinfo (cmsg->easy_handle,
914 CURLINFO_SIZE_UPLOAD_T,
915 &size_curl));
916
917 /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should
918 be an invariant.
919 As verified with
920 curl -w "foo%{size_request} -XPOST --data "ABC" $URL
921 the CURLINFO_REQUEST_SIZE should be the whole size of the request
922 including headers and body.
923 */
924 GNUNET_break (size_curl <= size_long);
925
926 urd = get_url_benchmark_data (url, (unsigned int) response_code);
927 urd->count++;
928 urd->time = GNUNET_TIME_relative_add (urd->time,
929 total);
930 urd->time_max = GNUNET_TIME_relative_max (total,
931 urd->time_max);
932 urd->bytes_sent += bytes_sent;
933 urd->bytes_received += bytes_received;
934}
935
936
937#endif
938
939
940/** 861/**
941 * Run the main event loop for the HTTP interaction. 862 * Run the main event loop for the HTTP interaction.
942 * 863 *
@@ -994,9 +915,6 @@ GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
994 response); 915 response);
995 rc (response); 916 rc (response);
996 } 917 }
997#if ENABLE_BENCHMARK
998 do_benchmark (cmsg);
999#endif
1000 GNUNET_CURL_job_cancel (job); 918 GNUNET_CURL_job_cancel (job);
1001 } 919 }
1002} 920}
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..9fda40f51 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) \
@@ -253,6 +254,7 @@ libgnunet_plugin_utiltest_la_LDFLAGS = \
253 254
254if HAVE_BENCHMARKS 255if HAVE_BENCHMARKS
255 BENCHMARKS = \ 256 BENCHMARKS = \
257 perf_crypto_cs \
256 perf_crypto_hash \ 258 perf_crypto_hash \
257 perf_crypto_rsa \ 259 perf_crypto_rsa \
258 perf_crypto_paillier \ 260 perf_crypto_paillier \
@@ -289,6 +291,7 @@ check_PROGRAMS = \
289 test_container_heap \ 291 test_container_heap \
290 test_crypto_symmetric \ 292 test_crypto_symmetric \
291 test_crypto_crc \ 293 test_crypto_crc \
294 test_crypto_cs \
292 test_crypto_ecdsa \ 295 test_crypto_ecdsa \
293 test_crypto_eddsa \ 296 test_crypto_eddsa \
294 test_crypto_ecdhe \ 297 test_crypto_ecdhe \
@@ -449,6 +452,12 @@ test_crypto_crc_SOURCES = \
449test_crypto_crc_LDADD = \ 452test_crypto_crc_LDADD = \
450 libgnunetutil.la 453 libgnunetutil.la
451 454
455test_crypto_cs_SOURCES = \
456 test_crypto_cs.c
457test_crypto_cs_LDADD = \
458 libgnunetutil.la \
459 -lsodium
460
452test_crypto_ecdsa_SOURCES = \ 461test_crypto_ecdsa_SOURCES = \
453 test_crypto_ecdsa.c 462 test_crypto_ecdsa.c
454test_crypto_ecdsa_LDADD = \ 463test_crypto_ecdsa_LDADD = \
@@ -604,6 +613,11 @@ test_uri_SOURCES = \
604test_uri_LDADD = \ 613test_uri_LDADD = \
605 libgnunetutil.la 614 libgnunetutil.la
606 615
616perf_crypto_cs_SOURCES = \
617 perf_crypto_cs.c
618perf_crypto_cs_LDADD = \
619 libgnunetutil.la
620
607perf_crypto_hash_SOURCES = \ 621perf_crypto_hash_SOURCES = \
608 perf_crypto_hash.c 622 perf_crypto_hash.c
609perf_crypto_hash_LDADD = \ 623perf_crypto_hash_LDADD = \
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}
diff --git a/src/util/perf_crypto_cs.c b/src/util/perf_crypto_cs.c
new file mode 100644
index 000000000..a8c72052b
--- /dev/null
+++ b/src/util/perf_crypto_cs.c
@@ -0,0 +1,185 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014 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 * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
23 * @author Gian Demarmels <gian@demarmels.org>
24 * @file util/perf_crypto_cs.c
25 * @brief measure performance of Clause Blind Schnorr Signatures
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <gauger.h>
31
32#define ITER 10
33
34/**
35 * Evaluate Clause Blind Schnorr Signature performance.
36 *
37 */
38static void
39eval ()
40{
41 struct GNUNET_TIME_Absolute start;
42 unsigned int i;
43
44 struct GNUNET_CRYPTO_CsPrivateKey priv;
45 struct GNUNET_CRYPTO_CsPublicKey pub;
46
47 struct GNUNET_CRYPTO_CsRSecret r_priv[2];
48 struct GNUNET_CRYPTO_CsRPublic r_pub[2];
49
50 char message[] = "test message";
51 size_t message_len = strlen ("test message");
52
53 // derive a test nonce
54 struct GNUNET_CRYPTO_CsNonce nonce;
55 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_hkdf (nonce.nonce,
56 sizeof(nonce.nonce),
57 GCRY_MD_SHA512,
58 GCRY_MD_SHA256,
59 "nonce",
60 strlen ("nonce"),
61 "nonce_secret",
62 strlen ("nonce_secret"),
63 NULL,
64 0));
65
66 struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
67 struct GNUNET_CRYPTO_CsC blinded_cs[2];
68 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2];
69 struct GNUNET_CRYPTO_CsBlindS blinded_s;
70 struct GNUNET_CRYPTO_CsS signature_scalar;
71 struct GNUNET_CRYPTO_CsSignature sig;
72
73 // BENCHMARK keygen
74 start = GNUNET_TIME_absolute_get ();
75
76 for (i = 0; i < ITER; i++)
77 {
78 GNUNET_CRYPTO_cs_private_key_generate (&priv);
79 GNUNET_CRYPTO_cs_private_key_get_public (&priv, &pub);
80 }
81 printf ("10x key generation took %s\n",
82 GNUNET_STRINGS_relative_time_to_string (
83 GNUNET_TIME_absolute_get_duration (start),
84 GNUNET_YES));
85
86
87 // BENCHMARK r derive and calc R pub
88 start = GNUNET_TIME_absolute_get ();
89 for (i = 0; i < ITER; i++)
90 {
91 GNUNET_CRYPTO_cs_r_derive (&nonce, &priv, r_priv);
92 GNUNET_CRYPTO_cs_r_get_public (&r_priv[0], &r_pub[0]);
93 GNUNET_CRYPTO_cs_r_get_public (&r_priv[1], &r_pub[1]);
94 }
95 printf ("10x r0, r1 derive and R1,R2 calculation took %s\n",
96 GNUNET_STRINGS_relative_time_to_string (
97 GNUNET_TIME_absolute_get_duration (start),
98 GNUNET_YES));
99
100
101 // BENCHMARK derive blinding secrets
102 start = GNUNET_TIME_absolute_get ();
103 for (i = 0; i < ITER; i++)
104 {
105 GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce,
106 sizeof(struct
107 GNUNET_CRYPTO_CsNonce),
108 bs);
109 }
110 printf ("10x derive blinding secrets took %s\n",
111 GNUNET_STRINGS_relative_time_to_string (
112 GNUNET_TIME_absolute_get_duration (start),
113 GNUNET_YES));
114
115
116 // BENCHMARK calculating C
117 start = GNUNET_TIME_absolute_get ();
118 for (i = 0; i < ITER; i++)
119 {
120 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
121 r_pub,
122 &pub,
123 message,
124 message_len,
125 blinded_cs,
126 blinded_r_pub);
127 }
128 printf ("10x calculating the blinded c took %s\n",
129 GNUNET_STRINGS_relative_time_to_string (
130 GNUNET_TIME_absolute_get_duration (start),
131 GNUNET_YES));
132
133
134 // BENCHMARK sign derive
135 unsigned int b;
136 start = GNUNET_TIME_absolute_get ();
137 for (i = 0; i < ITER; i++)
138 {
139 b = GNUNET_CRYPTO_cs_sign_derive (&priv,
140 r_priv,
141 blinded_cs,
142 &nonce,
143 &blinded_s);
144 }
145 printf ("10x signing blinded c took %s\n",
146 GNUNET_STRINGS_relative_time_to_string (
147 GNUNET_TIME_absolute_get_duration (start),
148 GNUNET_YES));
149
150
151 // BENCHMARK unblind signature
152 start = GNUNET_TIME_absolute_get ();
153
154 for (i = 0; i < ITER; i++)
155 {
156 GNUNET_CRYPTO_cs_unblind (&blinded_s, &bs[b], &signature_scalar);
157 sig.r_point = blinded_r_pub[b];
158 sig.s_scalar = signature_scalar;
159 }
160 printf ("10x unblinding s took %s\n",
161 GNUNET_STRINGS_relative_time_to_string (
162 GNUNET_TIME_absolute_get_duration (start),
163 GNUNET_YES));
164
165 // BENCHMARK verify signature
166 start = GNUNET_TIME_absolute_get ();
167 for (i = 0; i < ITER; i++)
168 {
169 GNUNET_CRYPTO_cs_verify (&sig,
170 &pub,
171 message,
172 message_len);
173 }
174 printf ("10x verifying signatures took %s\n",
175 GNUNET_STRINGS_relative_time_to_string (
176 GNUNET_TIME_absolute_get_duration (start),
177 GNUNET_YES));
178}
179
180int
181main (int argc, char *argv[])
182{
183 eval ();
184 return 0;
185}
diff --git a/src/util/test_crypto_cs.c b/src/util/test_crypto_cs.c
new file mode 100644
index 000000000..2978fec0a
--- /dev/null
+++ b/src/util/test_crypto_cs.c
@@ -0,0 +1,533 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014,2015 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/test_crypto_cs.c
23 * @brief testcase for utility functions for clause blind schnorr signature scheme cryptography
24 * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
25 * @author Gian Demarmels <gian@demarmels.org>
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include <sodium.h>
30
31#define ITER 25
32
33void
34test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
35{
36 /* TEST 1
37 * Check that privkey is set
38 */
39 struct GNUNET_CRYPTO_CsPrivateKey other_priv;
40 memcpy (&other_priv.scalar, &priv->scalar, sizeof(other_priv.scalar));
41
42 GNUNET_CRYPTO_cs_private_key_generate (priv);
43
44 GNUNET_assert (0 != memcmp (&other_priv.scalar,
45 &priv->scalar,
46 sizeof(other_priv.scalar)));
47}
48
49
50void
51test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
52 struct GNUNET_CRYPTO_CsPublicKey *pub)
53{
54 /* TEST 1
55 * Check that pubkey is set
56 */
57 struct GNUNET_CRYPTO_CsPublicKey other_pub;
58 memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point));
59
60 GNUNET_CRYPTO_cs_private_key_get_public (priv, pub);
61
62 GNUNET_assert (0 != memcmp (&other_pub.point,
63 &pub->point,
64 sizeof(other_pub.point)));
65
66 /* TEST 2
67 * Check that pubkey is a valid point
68 */
69 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (pub->point.y));
70
71 /* TEST 3
72 * Check if function gives the same result for the same output
73 */
74 memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point));
75
76 for (int i = 0; i<ITER; i++) {
77 GNUNET_CRYPTO_cs_private_key_get_public (priv, pub);
78 GNUNET_assert (0 == memcmp (&other_pub.point,
79 &pub->point,
80 sizeof(other_pub.point)));
81 }
82}
83
84
85void
86test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce,
87 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
88 struct GNUNET_CRYPTO_CsRSecret r[2])
89{
90 /* TEST 1
91 * Check that r are set
92 */
93 struct GNUNET_CRYPTO_CsPrivateKey other_r[2];
94 memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
95
96 GNUNET_CRYPTO_cs_r_derive (nonce, priv, r);
97
98 GNUNET_assert (0 != memcmp (&other_r[0],
99 &r[0],
100 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
101
102 /* TEST 2
103 * Check if function gives the same result for the same input.
104 * This test ensures that the derivation is deterministic.
105 */
106 memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
107 for (int i = 0; i<ITER; i++) {
108 GNUNET_CRYPTO_cs_r_derive (nonce, priv, r);
109 GNUNET_assert (0 == memcmp (&other_r[0],
110 &r[0],
111 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
112 }
113}
114
115
116void
117test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
118 struct GNUNET_CRYPTO_CsRPublic *r_pub)
119{
120 /* TEST 1
121 * Check that r_pub is set
122 */
123 struct GNUNET_CRYPTO_CsRPublic other_r_pub;
124 memcpy (&other_r_pub.point, &r_pub->point, sizeof(other_r_pub.point));
125
126 GNUNET_CRYPTO_cs_r_get_public (r_priv, r_pub);
127
128 GNUNET_assert (0 != memcmp (&other_r_pub.point,
129 &r_pub->point,
130 sizeof(other_r_pub.point)));
131
132 /* TEST 2
133 * Check that r_pub is a valid point
134 */
135 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (r_pub->point.y));
136
137 /* TEST 3
138 * Check if function gives the same result for the same output
139 */
140 memcpy (&other_r_pub.point, &r_pub->point, sizeof(other_r_pub.point));
141 for (int i = 0; i<ITER; i++) {
142 GNUNET_CRYPTO_cs_r_get_public (r_priv, r_pub);
143 GNUNET_assert (0 == memcmp (&other_r_pub.point,
144 &r_pub->point,
145 sizeof(other_r_pub.point)));
146 }
147}
148
149
150void
151test_derive_blindingsecrets (const void *secret,
152 size_t secret_len,
153 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
154{
155 /* TEST 1
156 * Check that blinding secrets are set
157 */
158 struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2];
159 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
160 * 2);
161
162 GNUNET_CRYPTO_cs_blinding_secrets_derive (secret, secret_len, bs);
163
164 GNUNET_assert (0 != memcmp (&other_bs[0],
165 &bs[0],
166 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
167 * 2));
168
169 /* TEST 2
170 * Check if function gives the same result for the same input.
171 * This test ensures that the derivation is deterministic.
172 */
173 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
174 * 2);
175 for (int i = 0; i<ITER; i++) {
176 GNUNET_CRYPTO_cs_blinding_secrets_derive (secret, secret_len, bs);
177 GNUNET_assert (0 == memcmp (&other_bs[0],
178 &bs[0],
179 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
180 * 2));
181 }
182}
183
184
185void
186test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
187 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
188 const struct GNUNET_CRYPTO_CsPublicKey *pub,
189 const void *msg,
190 size_t msg_len,
191 struct GNUNET_CRYPTO_CsC blinded_cs[2],
192 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
193{
194 /* TEST 1
195 * Check that the blinded c's and blinded r's
196 */
197 struct GNUNET_CRYPTO_CsC other_blinded_c[2];
198 memcpy (&other_blinded_c[0],
199 &blinded_cs[0],
200 sizeof(struct GNUNET_CRYPTO_CsC) * 2);
201
202 struct GNUNET_CRYPTO_CsRPublic other_blinded_r_pub[2];
203 memcpy (&other_blinded_r_pub[0],
204 &blinded_r_pub[0],
205 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
206
207 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
208 r_pub,
209 pub,
210 msg,
211 msg_len,
212 blinded_cs,
213 blinded_r_pub);
214
215 GNUNET_assert (0 != memcmp (&other_blinded_c[0],
216 &blinded_cs[0],
217 sizeof(struct GNUNET_CRYPTO_CsC) * 2));
218 GNUNET_assert (0 != memcmp (&other_blinded_r_pub[0],
219 &blinded_r_pub[0],
220 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
221
222 /* TEST 2
223 * Check if R' - aG -bX = R for b = 0
224 * This test does the opposite operations and checks wether the equation is still correct.
225 */
226 for (unsigned int b = 0; b <= 1; b++) {
227 struct GNUNET_CRYPTO_Cs25519Point aG;
228 struct GNUNET_CRYPTO_Cs25519Point bX;
229 struct GNUNET_CRYPTO_Cs25519Point r_min_aG;
230 struct GNUNET_CRYPTO_CsRPublic res;
231
232 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
233 aG.y,
234 bs[b].alpha.d));
235
236 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (
237 bX.y,
238 bs[b].beta.d,
239 pub->point.y));
240
241 GNUNET_assert (0 == crypto_core_ed25519_sub (
242 r_min_aG.y,
243 blinded_r_pub[b].point.y,
244 aG.y));
245
246 GNUNET_assert (0 == crypto_core_ed25519_sub (
247 res.point.y,
248 r_min_aG.y,
249 bX.y));
250
251 GNUNET_assert (0 == memcmp (&res, &r_pub[b], sizeof(struct
252 GNUNET_CRYPTO_CsRPublic)));
253 }
254
255
256
257 /* TEST 3
258 * Check that the blinded r_pubs' are valid points
259 */
260 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
261 blinded_r_pub[0].point.y));
262 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
263 blinded_r_pub[1].point.y));
264
265 /* TEST 4
266 * Check if function gives the same result for the same input.
267 */
268 memcpy (&other_blinded_c[0],
269 &blinded_cs[0],
270 sizeof(struct GNUNET_CRYPTO_CsC) * 2);
271 memcpy (&other_blinded_r_pub[0],
272 &blinded_r_pub[0],
273 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
274
275 for (int i = 0; i<ITER; i++) {
276 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
277 r_pub,
278 pub,
279 msg,
280 msg_len,
281 blinded_cs,
282 blinded_r_pub);
283 GNUNET_assert (0 == memcmp (&other_blinded_c[0],
284 &blinded_cs[0],
285 sizeof(struct GNUNET_CRYPTO_CsC) * 2));
286 GNUNET_assert (0 == memcmp (&other_blinded_r_pub[0],
287 &blinded_r_pub[0],
288 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
289 }
290}
291
292
293void
294test_blind_sign (unsigned int *b,
295 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
296 const struct GNUNET_CRYPTO_CsRSecret r[2],
297 const struct GNUNET_CRYPTO_CsC c[2],
298 const struct GNUNET_CRYPTO_CsNonce *nonce,
299 struct GNUNET_CRYPTO_CsBlindS *blinded_s)
300{
301 /* TEST 1
302 * Check that blinded_s is set
303 */
304 struct GNUNET_CRYPTO_CsC other_blinded_s;
305 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
306
307 *b = GNUNET_CRYPTO_cs_sign_derive (priv,
308 r,
309 c,
310 nonce,
311 blinded_s);
312
313 GNUNET_assert (0 == *b || 1 == *b);
314 GNUNET_assert (0 != memcmp (&other_blinded_s,
315 blinded_s,
316 sizeof(struct GNUNET_CRYPTO_CsBlindS)));
317
318 /* TEST 2
319 * Check if s := rb + cbX
320 * This test does the opposite operations and checks wether the equation is still correct.
321 */
322 struct GNUNET_CRYPTO_Cs25519Scalar cb_mul_x;
323 struct GNUNET_CRYPTO_Cs25519Scalar s_min_rb;
324
325 crypto_core_ed25519_scalar_mul (cb_mul_x.d,
326 c[*b].scalar.d,
327 priv->scalar.d);
328
329 crypto_core_ed25519_scalar_sub (s_min_rb.d,
330 blinded_s->scalar.d,
331 r[*b].scalar.d);
332
333 GNUNET_assert (0 == memcmp (&s_min_rb, &cb_mul_x, sizeof(struct
334 GNUNET_CRYPTO_Cs25519Scalar)));
335
336 /* TEST 3
337 * Check if function gives the same result for the same input.
338 */
339 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
340 unsigned int other_b;
341 for (int i = 0; i<ITER; i++) {
342 other_b = GNUNET_CRYPTO_cs_sign_derive (priv, r, c, nonce, blinded_s);
343
344 GNUNET_assert (other_b == *b);
345 GNUNET_assert (0 == memcmp (&other_blinded_s,
346 blinded_s,
347 sizeof(struct GNUNET_CRYPTO_CsBlindS)));
348 }
349}
350
351
352void
353test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
354 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
355 struct GNUNET_CRYPTO_CsS *signature_scalar)
356{
357 /* TEST 1
358 * Check that signature_scalar is set
359 */
360 struct GNUNET_CRYPTO_CsS other_signature_scalar;
361 memcpy (&other_signature_scalar,
362 signature_scalar,
363 sizeof(struct GNUNET_CRYPTO_CsS));
364
365 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
366
367 GNUNET_assert (0 != memcmp (&other_signature_scalar,
368 signature_scalar,
369 sizeof(struct GNUNET_CRYPTO_CsS)));
370
371 /* TEST 2
372 * Check if s' := s + a mod p
373 * This test does the opposite operations and checks wether the equation is still correct.
374 */
375 struct GNUNET_CRYPTO_Cs25519Scalar s_min_a;
376
377 crypto_core_ed25519_scalar_sub (s_min_a.d,
378 signature_scalar->scalar.d,
379 bs->alpha.d);
380
381 GNUNET_assert (0 == memcmp (&s_min_a, &blinded_signature_scalar->scalar,
382 sizeof(struct
383 GNUNET_CRYPTO_Cs25519Scalar)));
384
385 /* TEST 3
386 * Check if function gives the same result for the same input.
387 */
388 memcpy (&other_signature_scalar, signature_scalar,
389 sizeof(struct GNUNET_CRYPTO_CsS));
390
391 for (int i = 0; i<ITER; i++) {
392 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
393 GNUNET_assert (0 == memcmp (&other_signature_scalar,
394 signature_scalar,
395 sizeof(struct GNUNET_CRYPTO_CsS)));
396 }
397}
398
399
400void
401test_blind_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
402 const struct GNUNET_CRYPTO_CsPublicKey *pub,
403 const struct GNUNET_CRYPTO_CsC *c)
404{
405 /* TEST 1
406 * Test verifies the blinded signature sG == Rb + cbX
407 */
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
413 struct GNUNET_CRYPTO_Cs25519Point c_mul_pub;
414 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_mul_pub.y,
415 c->scalar.d,
416 pub->point.y));
417
418 struct GNUNET_CRYPTO_Cs25519Point r_add_c_mul_pub;
419 GNUNET_assert (0 == crypto_core_ed25519_add (r_add_c_mul_pub.y,
420 sig->r_point.point.y,
421 c_mul_pub.y));
422
423 GNUNET_assert (0 == memcmp (sig_scal_mul_base.y,
424 r_add_c_mul_pub.y,
425 sizeof(struct GNUNET_CRYPTO_Cs25519Point)));
426}
427
428
429void
430test_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
431 const struct GNUNET_CRYPTO_CsPublicKey *pub,
432 const void *msg,
433 size_t msg_len)
434{
435 /* TEST 1
436 * Test simple verification
437 */
438 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_cs_verify (sig,
439 pub,
440 msg,
441 msg_len));
442 /* TEST 2
443 * Test verification of "wrong" message
444 */
445 char other_msg[] = "test massege";
446 size_t other_msg_len = strlen ("test massege");
447 GNUNET_assert (GNUNET_SYSERR == GNUNET_CRYPTO_cs_verify (sig,
448 pub,
449 other_msg,
450 other_msg_len));
451}
452
453
454int
455main (int argc,
456 char *argv[])
457{
458 printf ("Test started\n");
459
460 // ---------- actions performed by signer
461 char message[] = "test message";
462 size_t message_len = strlen ("test message");
463
464 struct GNUNET_CRYPTO_CsPrivateKey priv;
465 test_create_priv (&priv);
466
467 struct GNUNET_CRYPTO_CsPublicKey pub;
468 test_generate_pub (&priv, &pub);
469
470 // derive nonce
471 struct GNUNET_CRYPTO_CsNonce nonce;
472 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_hkdf (nonce.nonce,
473 sizeof(nonce.nonce),
474 GCRY_MD_SHA512,
475 GCRY_MD_SHA256,
476 "nonce",
477 strlen ("nonce"),
478 "nonce_secret",
479 strlen ("nonce_secret"),
480 NULL,
481 0));
482
483 // generate r, R
484 struct GNUNET_CRYPTO_CsRSecret r_secrets[2];
485 test_derive_rsecret (&nonce, &priv, r_secrets);
486
487 struct GNUNET_CRYPTO_CsRPublic r_publics[2];
488 test_generate_rpublic (&r_secrets[0], &r_publics[0]);
489 test_generate_rpublic (&r_secrets[1], &r_publics[1]);
490
491 // ---------- actions performed by user
492
493 // generate blinding secrets
494 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2];
495 test_derive_blindingsecrets (&nonce,
496 sizeof(nonce),
497 blindingsecrets);
498
499 // calculate blinded c's
500 struct GNUNET_CRYPTO_CsC blinded_cs[2];
501 struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2];
502 test_calc_blindedc (blindingsecrets,
503 r_publics,
504 &pub,
505 message,
506 message_len,
507 blinded_cs,
508 blinded_r_pubs);
509
510 // ---------- actions performed by signer
511 // sign blinded c's and get b and s in return
512 unsigned int b;
513 struct GNUNET_CRYPTO_CsBlindS blinded_s;
514 test_blind_sign (&b, &priv, r_secrets, blinded_cs, &nonce, &blinded_s);
515
516 // verify blinded signature
517 struct GNUNET_CRYPTO_CsSignature blinded_signature;
518 blinded_signature.r_point = r_publics[b];
519 blinded_signature.s_scalar.scalar = blinded_s.scalar;
520 test_blind_verify (&blinded_signature, &pub, &blinded_cs[b]);
521
522 // ---------- actions performed by user
523 struct GNUNET_CRYPTO_CsS sig_scalar;
524 test_unblinds (&blinded_s, &blindingsecrets[b], &sig_scalar);
525
526 // verify unblinded signature
527 struct GNUNET_CRYPTO_CsSignature signature;
528 signature.r_point = blinded_r_pubs[b];
529 signature.s_scalar = sig_scalar;
530 test_verify (&signature, &pub, message, message_len);
531
532 return 0;
533}