/*
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;
}