/*
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
*/
/**
* @file util/test_crypto_paillier.c
* @brief testcase paillier crypto
* @author Christian Fuchs
* @author Florian Dold
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include
static int
test_crypto ()
{
gcry_mpi_t plaintext;
gcry_mpi_t plaintext_result;
struct GNUNET_CRYPTO_PaillierCiphertext ciphertext;
struct GNUNET_CRYPTO_PaillierPublicKey public_key;
struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
int ret = 0;
GNUNET_CRYPTO_paillier_create (&public_key,
&private_key);
GNUNET_assert (NULL != (plaintext = gcry_mpi_new (0)));
GNUNET_assert (NULL != (plaintext_result = gcry_mpi_new (0)));
gcry_mpi_randomize (plaintext,
GNUNET_CRYPTO_PAILLIER_BITS / 2,
GCRY_WEAK_RANDOM);
GNUNET_CRYPTO_paillier_encrypt (&public_key,
plaintext,
0 /* 0 hom ops */,
&ciphertext);
GNUNET_CRYPTO_paillier_decrypt (&private_key,
&public_key,
&ciphertext,
plaintext_result);
if (0 != gcry_mpi_cmp (plaintext,
plaintext_result))
{
fprintf (stderr,
"Paillier decryption failed with plaintext of size %u\n",
gcry_mpi_get_nbits (plaintext));
gcry_log_debugmpi ("\n",
plaintext);
gcry_log_debugmpi ("\n",
plaintext_result);
ret = 1;
}
gcry_mpi_release (plaintext);
gcry_mpi_release (plaintext_result);
return ret;
}
static int
test_hom_simple (unsigned int a,
unsigned int b)
{
gcry_mpi_t m1;
gcry_mpi_t m2;
gcry_mpi_t result;
gcry_mpi_t hom_result;
struct GNUNET_CRYPTO_PaillierCiphertext c1;
struct GNUNET_CRYPTO_PaillierCiphertext c2;
struct GNUNET_CRYPTO_PaillierCiphertext c_result;
struct GNUNET_CRYPTO_PaillierPublicKey public_key;
struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
int ret = 0;
GNUNET_CRYPTO_paillier_create (&public_key,
&private_key);
GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
m1 = gcry_mpi_set_ui (m1, a);
m2 = gcry_mpi_set_ui (m2, b);
gcry_mpi_add (result,
m1,
m2);
GNUNET_CRYPTO_paillier_encrypt (&public_key,
m1,
2,
&c1);
GNUNET_CRYPTO_paillier_encrypt (&public_key,
m2,
2,
&c2);
GNUNET_CRYPTO_paillier_hom_add (&public_key,
&c1,
&c2,
&c_result);
GNUNET_CRYPTO_paillier_decrypt (&private_key,
&public_key,
&c_result,
hom_result);
if (0 != gcry_mpi_cmp (result, hom_result))
{
fprintf (stderr,
"GNUNET_CRYPTO_paillier failed simple math!\n");
gcry_log_debugmpi ("got ", hom_result);
gcry_log_debugmpi ("wanted ", result);
ret = 1;
}
gcry_mpi_release (m1);
gcry_mpi_release (m2);
gcry_mpi_release (result);
gcry_mpi_release (hom_result);
return ret;
}
static int
test_hom ()
{
int ret;
gcry_mpi_t m1;
gcry_mpi_t m2;
gcry_mpi_t result;
gcry_mpi_t hom_result;
struct GNUNET_CRYPTO_PaillierCiphertext c1;
struct GNUNET_CRYPTO_PaillierCiphertext c2;
struct GNUNET_CRYPTO_PaillierCiphertext c_result;
struct GNUNET_CRYPTO_PaillierPublicKey public_key;
struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
GNUNET_CRYPTO_paillier_create (&public_key,
&private_key);
GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
m1 = gcry_mpi_set_ui (m1, 1);
/* m1 = m1 * 2 ^ (GCPB - 3) */
gcry_mpi_mul_2exp (m1,
m1,
GNUNET_CRYPTO_PAILLIER_BITS - 3);
m2 = gcry_mpi_set_ui (m2, 15);
/* m1 = m1 * 2 ^ (GCPB / 2) */
gcry_mpi_mul_2exp (m2,
m2,
GNUNET_CRYPTO_PAILLIER_BITS / 2);
gcry_mpi_add (result,
m1,
m2);
if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
m1,
2,
&c1)))
{
fprintf (stderr,
"GNUNET_CRYPTO_paillier_encrypt 1 failed, should return 1 allowed operation, got %d!\n",
ret);
ret = 1;
goto out;
}
if (2 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
m2,
2,
&c2)))
{
fprintf (stderr,
"GNUNET_CRYPTO_paillier_encrypt 2 failed, should return 2 allowed operation, got %d!\n",
ret);
ret = 1;
goto out;
}
if (0 != (ret = GNUNET_CRYPTO_paillier_hom_add (&public_key,
&c1,
&c2,
&c_result)))
{
fprintf (stderr,
"GNUNET_CRYPTO_paillier_hom_add failed, expected 0 remaining operations, got %d!\n",
ret);
ret = 1;
goto out;
}
GNUNET_CRYPTO_paillier_decrypt (&private_key,
&public_key,
&c_result,
hom_result);
if (0 != gcry_mpi_cmp (result, hom_result))
{
fprintf (stderr,
"GNUNET_CRYPTO_paillier miscalculated with large numbers!\n");
gcry_log_debugmpi ("got", hom_result);
gcry_log_debugmpi ("wanted", result);
ret = 1;
}
out:
gcry_mpi_release (m1);
gcry_mpi_release (m2);
gcry_mpi_release (result);
gcry_mpi_release (hom_result);
return ret;
}
int
main (int argc,
char *argv[])
{
int ret;
ret = test_crypto ();
if (0 != ret)
return ret;
ret = test_hom_simple (2, 4);
if (0 != ret)
return ret;
ret = test_hom_simple (13, 17);
if (0 != ret)
return ret;
ret = test_hom ();
return ret;
}
/* end of test_crypto_paillier.c */