Commit bf913c73 authored by Niels Möller's avatar Niels Möller

Implemented ECDSA key generation.

parent aaf43145
2013-02-20 Niels Möller <>
* ecdsa-keygen.c (ecdsa_generate_keypair): New file and function.
* (hogweed_SOURCES): Added ecdsa-keygen.c.
* testsuite/ecdsa-keygen-test.c: New testcase.
* testsuite/ (TS_HOGWEED_SOURCES): Added
* nettle-internal.h (TMP_ALLOC): Added missing parentheses.
2013-02-18 Niels Möller <>
......@@ -133,7 +133,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ecc-mul-g.c ecc-mul-a.c ecc-hash.c ecc-random.c \
ecc-point.c ecc-scalar.c \
ecc-ecdsa-sign.c ecdsa-sign.c \
ecc-ecdsa-verify.c ecdsa-verify.c
ecc-ecdsa-verify.c ecdsa-verify.c ecdsa-keygen.c
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
/* ecdsa-keygen.c */
/* nettle, low-level cryptographics library
* Copyright (C) 2013 Niels Möller
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
* The nettle library 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 Lesser General Public
* License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02111-1301, USA.
/* Development of Nettle's ECC support was funded by Internetfonden. */
# include "config.h"
#include <assert.h>
#include <stdlib.h>
#include "ecdsa.h"
#include "ecc-internal.h"
#include "nettle-internal.h"
ecdsa_generate_keypair (struct ecc_point *pub,
struct ecc_scalar *key,
void *random_ctx, nettle_random_func *random)
mp_size_t itch = 3*pub->ecc->size + ECC_MUL_G_ITCH (pub->ecc->size);
assert (key->ecc == pub->ecc);
TMP_ALLOC (p, itch);
ecc_modq_random (key->ecc, key->p, random_ctx, random, p);
ecc_mul_g (pub->ecc, p, key->p, p + 3*pub->ecc->size);
ecc_j_to_a (pub->ecc, 1, pub->p, p, p + 3*pub->ecc->size);
......@@ -23,6 +23,7 @@
......@@ -181,6 +181,9 @@ ecdsa-sign-test$(EXEEXT): ecdsa-sign-test.$(OBJEXT)
ecdsa-verify-test$(EXEEXT): ecdsa-verify-test.$(OBJEXT)
$(LINK) ecdsa-verify-test.$(OBJEXT) $(TEST_OBJS) -o ecdsa-verify-test$(EXEEXT)
ecdsa-keygen-test$(EXEEXT): ecdsa-keygen-test.$(OBJEXT)
$(LINK) ecdsa-keygen-test.$(OBJEXT) $(TEST_OBJS) -o ecdsa-keygen-test$(EXEEXT)
sha1-huge-test$(EXEEXT): sha1-huge-test.$(OBJEXT)
$(LINK) sha1-huge-test.$(OBJEXT) $(TEST_OBJS) -o sha1-huge-test$(EXEEXT)
......@@ -37,7 +37,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
dsa-test.c dsa-keygen-test.c \
ecc-mod-test.c ecc-modinv-test.c ecc-redc-test.c \
ecc-mul-g-test.c ecc-mul-a-test.c \
ecdsa-sign-test.c ecdsa-verify-test.c
ecdsa-sign-test.c ecdsa-verify-test.c ecdsa-keygen-test.c
CXX_SOURCES = cxx-test.cxx
#include "testutils.h"
#include <nettle/knuth-lfib.h>
/* Check if y^2 = x^3 - 3x + b */
static int
ecc_valid_p (struct ecc_point *pub)
mpz_t t, x, y;
mpz_t lhs, rhs;
int res;
mp_size_t size;
size = pub->ecc->size;
/* First check range */
if (mpn_cmp (pub->p, pub->ecc->p, size) >= 0
|| mpn_cmp (pub->p + size, pub->ecc->p, size) >= 0)
return 0;
mpz_init (lhs);
mpz_init (rhs);
_mpz_init_mpn (x, pub->p, size);
_mpz_init_mpn (y, pub->p + size, size);
mpz_mul (lhs, y, y);
mpz_mul (rhs, x, x);
mpz_sub_ui (rhs, rhs, 3);
mpz_mul (rhs, rhs, x);
mpz_add (rhs, rhs, _mpz_init_mpn (t, pub->ecc->b, size));
res = mpz_congruent_p (lhs, rhs, _mpz_init_mpn (t, pub->ecc->p, size));
mpz_clear (lhs);
mpz_clear (rhs);
return res;
test_main (void)
unsigned i;
struct knuth_lfib_ctx rctx;
struct dsa_signature signature;
struct tstring *digest;
knuth_lfib_init (&rctx, 4711);
dsa_signature_init (&signature);
digest = SHEX (/* sha256("abc") */
"BA7816BF 8F01CFEA 414140DE 5DAE2223"
"B00361A3 96177A9C B410FF61 F20015AD");
for (i = 0; ecc_curves[i]; i++)
const struct ecc_curve *ecc = ecc_curves[i];
struct ecc_point pub;
struct ecc_scalar key;
if (verbose)
fprintf (stderr, "Curve %d\n", ecc->bit_size);
ecc_point_init (&pub, ecc);
ecc_scalar_init (&key, ecc);
ecdsa_generate_keypair (&pub, &key,
(nettle_random_func *) knuth_lfib_random);
if (verbose)
gmp_fprintf (stderr,
"Public key:\nx = %Nx\ny = %Nx\n",
pub.p, ecc->size, pub.p + ecc->size, ecc->size);
gmp_fprintf (stderr,
"Private key: %Nx\n", key.p, ecc->size);
if (!ecc_valid_p (&pub))
die ("ecdsa_generate_keypair produced an invalid point.\n");
ecdsa_sign (&key,
&rctx, (nettle_random_func *) knuth_lfib_random,
digest->length, digest->data,
if (!ecdsa_verify (&pub, digest->length, digest->data,
die ("ecdsa_verify failed.\n");
digest->data[3] ^= 17;
if (ecdsa_verify (&pub, digest->length, digest->data,
die ("ecdsa_verify returned success with invalid digest.\n");
digest->data[3] ^= 17;
mpz_combit (signature.r, 117);
if (ecdsa_verify (&pub, digest->length, digest->data,
die ("ecdsa_verify returned success with invalid signature.r.\n");
mpz_combit (signature.r, 117);
mpz_combit (signature.s, 93);
if (ecdsa_verify (&pub, digest->length, digest->data,
die ("ecdsa_verify returned success with invalid signature.s.\n");
ecc_point_clear (&pub);
ecc_scalar_clear (&key);
dsa_signature_clear (&signature);
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment