From 67b56e366bc73cc9d940721067ae0f3c7f554768 Mon Sep 17 00:00:00 2001 From: Gian Demarmels Date: Mon, 6 Dec 2021 22:44:14 +0100 Subject: add crypto_cs testing and benchmark --- src/util/Makefile.am | 13 ++ src/util/perf_crypto_cs.c | 185 ++++++++++++++++ src/util/test_crypto_cs.c | 533 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 731 insertions(+) create mode 100644 src/util/perf_crypto_cs.c create mode 100644 src/util/test_crypto_cs.c (limited to 'src') diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 771be1ee3..9fda40f51 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -254,6 +254,7 @@ libgnunet_plugin_utiltest_la_LDFLAGS = \ if HAVE_BENCHMARKS BENCHMARKS = \ + perf_crypto_cs \ perf_crypto_hash \ perf_crypto_rsa \ perf_crypto_paillier \ @@ -290,6 +291,7 @@ check_PROGRAMS = \ test_container_heap \ test_crypto_symmetric \ test_crypto_crc \ + test_crypto_cs \ test_crypto_ecdsa \ test_crypto_eddsa \ test_crypto_ecdhe \ @@ -450,6 +452,12 @@ test_crypto_crc_SOURCES = \ test_crypto_crc_LDADD = \ libgnunetutil.la +test_crypto_cs_SOURCES = \ + test_crypto_cs.c +test_crypto_cs_LDADD = \ + libgnunetutil.la \ + -lsodium + test_crypto_ecdsa_SOURCES = \ test_crypto_ecdsa.c test_crypto_ecdsa_LDADD = \ @@ -605,6 +613,11 @@ test_uri_SOURCES = \ test_uri_LDADD = \ libgnunetutil.la +perf_crypto_cs_SOURCES = \ + perf_crypto_cs.c +perf_crypto_cs_LDADD = \ + libgnunetutil.la + perf_crypto_hash_SOURCES = \ perf_crypto_hash.c perf_crypto_hash_LDADD = \ 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 @@ +/* + This file is part of GNUnet. + Copyright (C) 2014 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @author Lucien Heuzeveldt + * @author Gian Demarmels + * @file util/perf_crypto_cs.c + * @brief measure performance of Clause Blind Schnorr Signatures + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include + +#define ITER 10 + +/** + * Evaluate Clause Blind Schnorr Signature performance. + * + */ +static void +eval () +{ + struct GNUNET_TIME_Absolute start; + unsigned int i; + + struct GNUNET_CRYPTO_CsPrivateKey priv; + struct GNUNET_CRYPTO_CsPublicKey pub; + + struct GNUNET_CRYPTO_CsRSecret r_priv[2]; + struct GNUNET_CRYPTO_CsRPublic r_pub[2]; + + char message[] = "test message"; + size_t message_len = strlen ("test message"); + + // derive a test nonce + struct GNUNET_CRYPTO_CsNonce nonce; + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_hkdf (nonce.nonce, + sizeof(nonce.nonce), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + "nonce", + strlen ("nonce"), + "nonce_secret", + strlen ("nonce_secret"), + NULL, + 0)); + + struct GNUNET_CRYPTO_CsBlindingSecret bs[2]; + struct GNUNET_CRYPTO_CsC blinded_cs[2]; + struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2]; + struct GNUNET_CRYPTO_CsBlindS blinded_s; + struct GNUNET_CRYPTO_CsS signature_scalar; + struct GNUNET_CRYPTO_CsSignature sig; + + // BENCHMARK keygen + start = GNUNET_TIME_absolute_get (); + + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_private_key_generate (&priv); + GNUNET_CRYPTO_cs_private_key_get_public (&priv, &pub); + } + printf ("10x key generation took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + + // BENCHMARK r derive and calc R pub + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_r_derive (&nonce, &priv, r_priv); + GNUNET_CRYPTO_cs_r_get_public (&r_priv[0], &r_pub[0]); + GNUNET_CRYPTO_cs_r_get_public (&r_priv[1], &r_pub[1]); + } + printf ("10x r0, r1 derive and R1,R2 calculation took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + + // BENCHMARK derive blinding secrets + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce, + sizeof(struct + GNUNET_CRYPTO_CsNonce), + bs); + } + printf ("10x derive blinding secrets took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + + // BENCHMARK calculating C + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_calc_blinded_c (bs, + r_pub, + &pub, + message, + message_len, + blinded_cs, + blinded_r_pub); + } + printf ("10x calculating the blinded c took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + + // BENCHMARK sign derive + unsigned int b; + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + b = GNUNET_CRYPTO_cs_sign_derive (&priv, + r_priv, + blinded_cs, + &nonce, + &blinded_s); + } + printf ("10x signing blinded c took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + + // BENCHMARK unblind signature + start = GNUNET_TIME_absolute_get (); + + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_unblind (&blinded_s, &bs[b], &signature_scalar); + sig.r_point = blinded_r_pub[b]; + sig.s_scalar = signature_scalar; + } + printf ("10x unblinding s took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); + + // BENCHMARK verify signature + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + GNUNET_CRYPTO_cs_verify (&sig, + &pub, + message, + message_len); + } + printf ("10x verifying signatures took %s\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (start), + GNUNET_YES)); +} + +int +main (int argc, char *argv[]) +{ + eval (); + return 0; +} 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 @@ +/* + This file is part of GNUnet + Copyright (C) 2014,2015 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @file util/test_crypto_cs.c + * @brief testcase for utility functions for clause blind schnorr signature scheme cryptography + * @author Lucien Heuzeveldt + * @author Gian Demarmels + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include + +#define ITER 25 + +void +test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv) +{ + /* TEST 1 + * Check that privkey is set + */ + struct GNUNET_CRYPTO_CsPrivateKey other_priv; + memcpy (&other_priv.scalar, &priv->scalar, sizeof(other_priv.scalar)); + + GNUNET_CRYPTO_cs_private_key_generate (priv); + + GNUNET_assert (0 != memcmp (&other_priv.scalar, + &priv->scalar, + sizeof(other_priv.scalar))); +} + + +void +test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey *priv, + struct GNUNET_CRYPTO_CsPublicKey *pub) +{ + /* TEST 1 + * Check that pubkey is set + */ + struct GNUNET_CRYPTO_CsPublicKey other_pub; + memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point)); + + GNUNET_CRYPTO_cs_private_key_get_public (priv, pub); + + GNUNET_assert (0 != memcmp (&other_pub.point, + &pub->point, + sizeof(other_pub.point))); + + /* TEST 2 + * Check that pubkey is a valid point + */ + GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (pub->point.y)); + + /* TEST 3 + * Check if function gives the same result for the same output + */ + memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point)); + + for (int i = 0; ipoint, + sizeof(other_pub.point))); + } +} + + +void +test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce, + const struct GNUNET_CRYPTO_CsPrivateKey *priv, + struct GNUNET_CRYPTO_CsRSecret r[2]) +{ + /* TEST 1 + * Check that r are set + */ + struct GNUNET_CRYPTO_CsPrivateKey other_r[2]; + memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2); + + GNUNET_CRYPTO_cs_r_derive (nonce, priv, r); + + GNUNET_assert (0 != memcmp (&other_r[0], + &r[0], + sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2)); + + /* TEST 2 + * Check if function gives the same result for the same input. + * This test ensures that the derivation is deterministic. + */ + memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2); + for (int i = 0; ipoint, sizeof(other_r_pub.point)); + + GNUNET_CRYPTO_cs_r_get_public (r_priv, r_pub); + + GNUNET_assert (0 != memcmp (&other_r_pub.point, + &r_pub->point, + sizeof(other_r_pub.point))); + + /* TEST 2 + * Check that r_pub is a valid point + */ + GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (r_pub->point.y)); + + /* TEST 3 + * Check if function gives the same result for the same output + */ + memcpy (&other_r_pub.point, &r_pub->point, sizeof(other_r_pub.point)); + for (int i = 0; ipoint, + sizeof(other_r_pub.point))); + } +} + + +void +test_derive_blindingsecrets (const void *secret, + size_t secret_len, + struct GNUNET_CRYPTO_CsBlindingSecret bs[2]) +{ + /* TEST 1 + * Check that blinding secrets are set + */ + struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2]; + memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) + * 2); + + GNUNET_CRYPTO_cs_blinding_secrets_derive (secret, secret_len, bs); + + GNUNET_assert (0 != memcmp (&other_bs[0], + &bs[0], + sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) + * 2)); + + /* TEST 2 + * Check if function gives the same result for the same input. + * This test ensures that the derivation is deterministic. + */ + memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) + * 2); + for (int i = 0; ipoint.y)); + + GNUNET_assert (0 == crypto_core_ed25519_sub ( + r_min_aG.y, + blinded_r_pub[b].point.y, + aG.y)); + + GNUNET_assert (0 == crypto_core_ed25519_sub ( + res.point.y, + r_min_aG.y, + bX.y)); + + GNUNET_assert (0 == memcmp (&res, &r_pub[b], sizeof(struct + GNUNET_CRYPTO_CsRPublic))); + } + + + + /* TEST 3 + * Check that the blinded r_pubs' are valid points + */ + GNUNET_assert (1 == crypto_core_ed25519_is_valid_point ( + blinded_r_pub[0].point.y)); + GNUNET_assert (1 == crypto_core_ed25519_is_valid_point ( + blinded_r_pub[1].point.y)); + + /* TEST 4 + * Check if function gives the same result for the same input. + */ + memcpy (&other_blinded_c[0], + &blinded_cs[0], + sizeof(struct GNUNET_CRYPTO_CsC) * 2); + memcpy (&other_blinded_r_pub[0], + &blinded_r_pub[0], + sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2); + + for (int i = 0; iscalar.d); + + crypto_core_ed25519_scalar_sub (s_min_rb.d, + blinded_s->scalar.d, + r[*b].scalar.d); + + GNUNET_assert (0 == memcmp (&s_min_rb, &cb_mul_x, sizeof(struct + GNUNET_CRYPTO_Cs25519Scalar))); + + /* TEST 3 + * Check if function gives the same result for the same input. + */ + memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS)); + unsigned int other_b; + for (int i = 0; iscalar.d, + bs->alpha.d); + + GNUNET_assert (0 == memcmp (&s_min_a, &blinded_signature_scalar->scalar, + sizeof(struct + GNUNET_CRYPTO_Cs25519Scalar))); + + /* TEST 3 + * Check if function gives the same result for the same input. + */ + memcpy (&other_signature_scalar, signature_scalar, + sizeof(struct GNUNET_CRYPTO_CsS)); + + for (int i = 0; is_scalar.scalar.d)); + + struct GNUNET_CRYPTO_Cs25519Point c_mul_pub; + GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_mul_pub.y, + c->scalar.d, + pub->point.y)); + + struct GNUNET_CRYPTO_Cs25519Point r_add_c_mul_pub; + GNUNET_assert (0 == crypto_core_ed25519_add (r_add_c_mul_pub.y, + sig->r_point.point.y, + c_mul_pub.y)); + + GNUNET_assert (0 == memcmp (sig_scal_mul_base.y, + r_add_c_mul_pub.y, + sizeof(struct GNUNET_CRYPTO_Cs25519Point))); +} + + +void +test_verify (const struct GNUNET_CRYPTO_CsSignature *sig, + const struct GNUNET_CRYPTO_CsPublicKey *pub, + const void *msg, + size_t msg_len) +{ + /* TEST 1 + * Test simple verification + */ + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_cs_verify (sig, + pub, + msg, + msg_len)); + /* TEST 2 + * Test verification of "wrong" message + */ + char other_msg[] = "test massege"; + size_t other_msg_len = strlen ("test massege"); + GNUNET_assert (GNUNET_SYSERR == GNUNET_CRYPTO_cs_verify (sig, + pub, + other_msg, + other_msg_len)); +} + + +int +main (int argc, + char *argv[]) +{ + printf ("Test started\n"); + + // ---------- actions performed by signer + char message[] = "test message"; + size_t message_len = strlen ("test message"); + + struct GNUNET_CRYPTO_CsPrivateKey priv; + test_create_priv (&priv); + + struct GNUNET_CRYPTO_CsPublicKey pub; + test_generate_pub (&priv, &pub); + + // derive nonce + struct GNUNET_CRYPTO_CsNonce nonce; + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_hkdf (nonce.nonce, + sizeof(nonce.nonce), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + "nonce", + strlen ("nonce"), + "nonce_secret", + strlen ("nonce_secret"), + NULL, + 0)); + + // generate r, R + struct GNUNET_CRYPTO_CsRSecret r_secrets[2]; + test_derive_rsecret (&nonce, &priv, r_secrets); + + struct GNUNET_CRYPTO_CsRPublic r_publics[2]; + test_generate_rpublic (&r_secrets[0], &r_publics[0]); + test_generate_rpublic (&r_secrets[1], &r_publics[1]); + + // ---------- actions performed by user + + // generate blinding secrets + struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2]; + test_derive_blindingsecrets (&nonce, + sizeof(nonce), + blindingsecrets); + + // calculate blinded c's + struct GNUNET_CRYPTO_CsC blinded_cs[2]; + struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2]; + test_calc_blindedc (blindingsecrets, + r_publics, + &pub, + message, + message_len, + blinded_cs, + blinded_r_pubs); + + // ---------- actions performed by signer + // sign blinded c's and get b and s in return + unsigned int b; + struct GNUNET_CRYPTO_CsBlindS blinded_s; + test_blind_sign (&b, &priv, r_secrets, blinded_cs, &nonce, &blinded_s); + + // verify blinded signature + struct GNUNET_CRYPTO_CsSignature blinded_signature; + blinded_signature.r_point = r_publics[b]; + blinded_signature.s_scalar.scalar = blinded_s.scalar; + test_blind_verify (&blinded_signature, &pub, &blinded_cs[b]); + + // ---------- actions performed by user + struct GNUNET_CRYPTO_CsS sig_scalar; + test_unblinds (&blinded_s, &blindingsecrets[b], &sig_scalar); + + // verify unblinded signature + struct GNUNET_CRYPTO_CsSignature signature; + signature.r_point = blinded_r_pubs[b]; + signature.s_scalar = sig_scalar; + test_verify (&signature, &pub, message, message_len); + + return 0; +} -- cgit v1.2.3