]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implemented ECDSA key generation.
authorNiels Möller <nisse@lysator.liu.se>
Wed, 20 Feb 2013 10:27:24 +0000 (11:27 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 20 Feb 2013 10:27:24 +0000 (11:27 +0100)
ChangeLog
Makefile.in
ecdsa-keygen.c [new file with mode: 0644]
testsuite/.gitignore
testsuite/.test-rules.make
testsuite/Makefile.in
testsuite/ecdsa-keygen-test.c [new file with mode: 0644]

index fa11ddc46ff496ac8b145d184983342381771883..fb9932a9626775e48f8626ca97ae7eddc090bae9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-02-20  Niels Möller  <nisse@lysator.liu.se>
 
+       * ecdsa-keygen.c (ecdsa_generate_keypair): New file and function.
+       * Makefile.in (hogweed_SOURCES): Added ecdsa-keygen.c.
+       * testsuite/ecdsa-keygen-test.c: New testcase.
+       * testsuite/Makefile.in (TS_HOGWEED_SOURCES): Added
+       ecdsa-keygen-test.c.
+
        * nettle-internal.h (TMP_ALLOC): Added missing parentheses.
 
 2013-02-18  Niels Möller  <nisse@lysator.liu.se>
index 958278df51ae0b98ed2f05558a668a6368372757..a327b0bf4af06ba96d9748bb582a07dcecde0f10 100644 (file)
@@ -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 \
diff --git a/ecdsa-keygen.c b/ecdsa-keygen.c
new file mode 100644 (file)
index 0000000..7f8a37f
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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. */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "ecdsa.h"
+#include "ecc-internal.h"
+#include "nettle-internal.h"
+
+void
+ecdsa_generate_keypair (struct ecc_point *pub,
+                       struct ecc_scalar *key,
+                       void *random_ctx, nettle_random_func *random)
+{
+  TMP_DECL(p, mp_limb_t, 3*ECC_MAX_SIZE + ECC_MUL_G_ITCH (ECC_MAX_SIZE));
+  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);
+}
index a5b83b51fffb77410d7e3ada1442c4c2aa964b98..642d8c42d47f6143aad7ff1a14df4a6ba55c9e7c 100644 (file)
@@ -23,6 +23,7 @@
 /ecc-mul-a-test
 /ecc-mul-g-test
 /ecc-redc-test
+/ecdsa-keygen-test
 /ecdsa-sign-test
 /ecdsa-verify-test
 /gcm-test
index f23f2515ec0f2b20192c7361a7d198f158a0758f..a935171d209c6a1be314d57cceeaa97ada305a70 100644 (file)
@@ -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)
 
index 847c01d7d38dd5c0132928844a97b03377e10153..a155b447b0a41249c1aca65f7daf68d327fee32a 100644 (file)
@@ -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
 
 TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES)
 CXX_SOURCES = cxx-test.cxx
diff --git a/testsuite/ecdsa-keygen-test.c b/testsuite/ecdsa-keygen-test.c
new file mode 100644 (file)
index 0000000..375820c
--- /dev/null
@@ -0,0 +1,113 @@
+#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;
+}
+
+void
+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,
+                             &rctx,
+                             (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,
+                 &signature);
+
+      if (!ecdsa_verify (&pub, digest->length, digest->data,
+                         &signature))
+       die ("ecdsa_verify failed.\n");
+
+      digest->data[3] ^= 17;
+      if (ecdsa_verify (&pub, digest->length, digest->data,
+                        &signature))
+       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,
+                        &signature))
+       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,
+                        &signature))
+       die ("ecdsa_verify  returned success with invalid signature.s.\n");
+
+      ecc_point_clear (&pub);
+      ecc_scalar_clear (&key);
+    }
+  dsa_signature_clear (&signature);
+}