/*
This file is part of GNUnet
Copyright (C) 2021,2022 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
static void
test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
{
/* TEST 1
* Check that privkey is set
*/
struct GNUNET_CRYPTO_CsPrivateKey other_priv;
other_priv = *priv;
GNUNET_CRYPTO_cs_private_key_generate (priv);
GNUNET_assert (0 !=
GNUNET_memcmp (&other_priv.scalar,
&priv->scalar));
}
static 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;
other_pub = *pub;
GNUNET_CRYPTO_cs_private_key_get_public (priv,
pub);
GNUNET_assert (0 !=
GNUNET_memcmp (&other_pub.point,
&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
*/
other_pub = *pub;
for (unsigned int i = 0; ipoint));
}
}
static 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,
r,
sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
GNUNET_CRYPTO_cs_r_derive (nonce,
"nw",
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,
r,
sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
for (unsigned int i = 0; ipoint));
/* 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
*/
other_r_pub.point = r_pub->point;
for (int i = 0; ipoint));
}
}
static void
test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
{
/* TEST 1
* Check that blinding secrets are set
*/
struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2];
memcpy (other_bs,
bs,
sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
GNUNET_assert (0 !=
memcmp (other_bs,
bs,
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,
bs,
sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
for (unsigned 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 (unsigned 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));
for (unsigned 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 (unsigned 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)));
}
static 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;
memset (&priv,
42,
sizeof (priv));
test_create_priv (&priv);
struct GNUNET_CRYPTO_CsPublicKey pub;
memset (&pub,
42,
sizeof (pub));
test_generate_pub (&priv,
&pub);
// derive nonce
struct GNUNET_CRYPTO_CsNonce nonce;
GNUNET_assert (GNUNET_YES ==
GNUNET_CRYPTO_kdf (nonce.nonce,
sizeof(nonce.nonce),
"nonce",
strlen ("nonce"),
"nonce_secret",
strlen ("nonce_secret"),
NULL,
0));
// generate r, R
struct GNUNET_CRYPTO_CsRSecret r_secrets[2];
memset (r_secrets,
42,
sizeof (r_secrets));
test_derive_rsecret (&nonce,
&priv,
r_secrets);
struct GNUNET_CRYPTO_CsRPublic r_publics[2];
memset (r_publics,
42,
sizeof (r_publics));
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];
memset (blindingsecrets,
42,
sizeof (blindingsecrets));
test_derive_blindingsecrets (&nonce,
blindingsecrets);
// calculate blinded c's
struct GNUNET_CRYPTO_CsC blinded_cs[2];
struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2];
memset (blinded_cs,
42,
sizeof (blinded_cs));
memset (blinded_r_pubs,
42,
sizeof (blinded_r_pubs));
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;
memset (&blinded_s,
42,
sizeof (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;
memset (&sig_scalar,
42,
sizeof (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;
}