diff options
author | t3sserakt <t3ss@posteo.de> | 2021-12-08 07:57:47 +0100 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2021-12-08 07:58:12 +0100 |
commit | b46bf463d56475edd777cfa7f4209d6fc7c648cd (patch) | |
tree | 7b3665c6ff8af603d971a4e85397f3d5f8523609 /src | |
parent | 91eec8adabb74b6488a01c45927dfb7c85e1a45e (diff) | |
parent | 67b56e366bc73cc9d940721067ae0f3c7f554768 (diff) | |
download | gnunet-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.c | 82 | ||||
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 270 | ||||
-rw-r--r-- | src/util/Makefile.am | 14 | ||||
-rw-r--r-- | src/util/crypto_cs.c | 425 | ||||
-rw-r--r-- | src/util/perf_crypto_cs.c | 185 | ||||
-rw-r--r-- | src/util/test_crypto_cs.c | 533 |
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 | ||
862 | static void | ||
863 | do_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 | */ | ||
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..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 | ||
254 | if HAVE_BENCHMARKS | 255 | if 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 = \ | |||
449 | test_crypto_crc_LDADD = \ | 452 | test_crypto_crc_LDADD = \ |
450 | libgnunetutil.la | 453 | libgnunetutil.la |
451 | 454 | ||
455 | test_crypto_cs_SOURCES = \ | ||
456 | test_crypto_cs.c | ||
457 | test_crypto_cs_LDADD = \ | ||
458 | libgnunetutil.la \ | ||
459 | -lsodium | ||
460 | |||
452 | test_crypto_ecdsa_SOURCES = \ | 461 | test_crypto_ecdsa_SOURCES = \ |
453 | test_crypto_ecdsa.c | 462 | test_crypto_ecdsa.c |
454 | test_crypto_ecdsa_LDADD = \ | 463 | test_crypto_ecdsa_LDADD = \ |
@@ -604,6 +613,11 @@ test_uri_SOURCES = \ | |||
604 | test_uri_LDADD = \ | 613 | test_uri_LDADD = \ |
605 | libgnunetutil.la | 614 | libgnunetutil.la |
606 | 615 | ||
616 | perf_crypto_cs_SOURCES = \ | ||
617 | perf_crypto_cs.c | ||
618 | perf_crypto_cs_LDADD = \ | ||
619 | libgnunetutil.la | ||
620 | |||
607 | perf_crypto_hash_SOURCES = \ | 621 | perf_crypto_hash_SOURCES = \ |
608 | perf_crypto_hash.c | 622 | perf_crypto_hash.c |
609 | perf_crypto_hash_LDADD = \ | 623 | perf_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 | */ | ||
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 | } | ||
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 | */ | ||
38 | static void | ||
39 | eval () | ||
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 | |||
180 | int | ||
181 | main (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 | |||
33 | void | ||
34 | test_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 | |||
50 | void | ||
51 | test_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 | |||
85 | void | ||
86 | test_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 | |||
116 | void | ||
117 | test_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 | |||
150 | void | ||
151 | test_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 | |||
185 | void | ||
186 | test_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 | |||
293 | void | ||
294 | test_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 | |||
352 | void | ||
353 | test_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 | |||
400 | void | ||
401 | test_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 | |||
429 | void | ||
430 | test_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 | |||
454 | int | ||
455 | main (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 | } | ||