/*
This file is part of GNUnet.
Copyright (C) 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_ecc_scalarproduct.c
* @brief testcase for math behind ECC SP calculation
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include
/**
* Global context.
*/
static struct GNUNET_CRYPTO_EccDlogContext *edc;
/**
* Perform SP calculation.
*
* @param avec 0-terminated vector of Alice's values
* @param bvec 0-terminated vector of Bob's values
* @return avec * bvec
*/
static int
test_sp (const unsigned int *avec,
const unsigned int *bvec)
{
unsigned int len;
unsigned int i;
gcry_mpi_t a;
gcry_mpi_t a_inv;
gcry_mpi_t ri;
gcry_mpi_t val;
gcry_mpi_t ria;
gcry_mpi_t tmp;
gcry_mpi_point_t *g;
gcry_mpi_point_t *h;
gcry_mpi_point_t pg;
gcry_mpi_point_t ph;
gcry_mpi_point_t pgi;
gcry_mpi_point_t gsp;
int sp;
/* determine length */
for (len = 0; 0 != avec[len]; len++)
;
if (0 == len)
return 0;
/* Alice */
GNUNET_CRYPTO_ecc_rnd_mpi (edc,
&a, &a_inv);
g = GNUNET_new_array (len,
gcry_mpi_point_t);
h = GNUNET_new_array (len,
gcry_mpi_point_t);
ria = gcry_mpi_new (0);
tmp = gcry_mpi_new (0);
for (i = 0; i < len; i++)
{
ri = GNUNET_CRYPTO_ecc_random_mod_n (edc);
g[i] = GNUNET_CRYPTO_ecc_dexp_mpi (edc,
ri);
/* ria = ri * a */
gcry_mpi_mul (ria,
ri,
a);
/* tmp = ria + avec[i] */
gcry_mpi_add_ui (tmp,
ria,
avec[i]);
h[i] = GNUNET_CRYPTO_ecc_dexp_mpi (edc,
tmp);
}
gcry_mpi_release (ria);
gcry_mpi_release (tmp);
/* Bob */
val = gcry_mpi_new (0);
gcry_mpi_set_ui (val, bvec[0]);
pg = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
g[0],
val);
ph = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
h[0],
val);
for (i = 1; i < len; i++)
{
gcry_mpi_point_t m;
gcry_mpi_point_t tmp;
gcry_mpi_set_ui (val, bvec[i]);
m = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
g[i],
val);
tmp = GNUNET_CRYPTO_ecc_add (edc,
m,
pg);
gcry_mpi_point_release (m);
gcry_mpi_point_release (pg);
gcry_mpi_point_release (g[i]);
pg = tmp;
m = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
h[i],
val);
tmp = GNUNET_CRYPTO_ecc_add (edc,
m,
ph);
gcry_mpi_point_release (m);
gcry_mpi_point_release (ph);
gcry_mpi_point_release (h[i]);
ph = tmp;
}
gcry_mpi_release (val);
GNUNET_free (g);
GNUNET_free (h);
/* Alice */
pgi = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
pg,
a_inv);
gsp = GNUNET_CRYPTO_ecc_add (edc,
pgi,
ph);
gcry_mpi_point_release (pgi);
gcry_mpi_point_release (ph);
sp = GNUNET_CRYPTO_ecc_dlog (edc,
gsp);
gcry_mpi_point_release (gsp);
return sp;
}
int
main (int argc, char *argv[])
{
static unsigned int v11[] = { 1, 1, 0 };
static unsigned int v22[] = { 2, 2, 0 };
static unsigned int v35[] = { 3, 5, 0 };
static unsigned int v24[] = { 2, 4, 0 };
GNUNET_log_setup ("test-ecc-scalarproduct",
"WARNING",
NULL);
edc = GNUNET_CRYPTO_ecc_dlog_prepare (128, 128);
GNUNET_assert (2 == test_sp (v11, v11));
GNUNET_assert (4 == test_sp (v22, v11));
GNUNET_assert (8 == test_sp (v35, v11));
GNUNET_assert (26 == test_sp (v35, v24));
GNUNET_assert (26 == test_sp (v24, v35));
GNUNET_assert (16 == test_sp (v22, v35));
GNUNET_CRYPTO_ecc_dlog_release (edc);
return 0;
}
/* end of test_ecc_scalarproduct.c */