gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: Fix ECDSA/ECDH key exchange


From: gnunet
Subject: [gnunet] branch master updated: Fix ECDSA/ECDH key exchange
Date: Mon, 06 Jan 2020 14:08:55 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 1ad2fb331 Fix ECDSA/ECDH key exchange
1ad2fb331 is described below

commit 1ad2fb331548adf635e9cff8786b468e54666371
Author: Florian Dold <address@hidden>
AuthorDate: Mon Jan 6 14:02:40 2020 +0100

    Fix ECDSA/ECDH key exchange
    
    Libgcrypt interprets the private key as little endian, while tweetnacl
    interprets it as big endian.  This caused the key exchange to fail.
---
 src/util/.gitignore         |   1 +
 src/util/crypto_ecc.c       | 109 ++++++++------------------------------------
 src/util/tweetnacl-gnunet.c |  21 ++++++++-
 src/util/tweetnacl-gnunet.h |   4 ++
 4 files changed, 42 insertions(+), 93 deletions(-)

diff --git a/src/util/.gitignore b/src/util/.gitignore
index 01ebcc834..0495dcf8f 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -30,6 +30,7 @@ test_container_multihashmap32
 test_container_multipeermap
 test_crypto_crc
 test_crypto_ecc_dlog
+test_crypto_ecdh_ecdsa
 test_crypto_ecdh_eddsa
 test_crypto_ecdhe
 test_crypto_ecdsa
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index bd7c425d4..d4cfaa72c 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -173,22 +173,8 @@ GNUNET_CRYPTO_ecdsa_key_get_public (
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
   struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
 {
-  gcry_sexp_t sexp;
-  gcry_ctx_t ctx;
-  gcry_mpi_t q;
-
   BENCHMARK_START (ecdsa_key_get_public);
-
-  sexp = decode_private_ecdsa_key (priv);
-  GNUNET_assert (NULL != sexp);
-  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
-  gcry_sexp_release (sexp);
-  q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
-  GNUNET_assert (NULL != q);
-  GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
-  gcry_mpi_release (q);
-  gcry_ctx_release (ctx);
-
+  GNUNET_TWEETNACL_scalarmult_le_ed25519_base (pub->q_y, priv->d);
   BENCHMARK_END (ecdsa_key_get_public);
 }
 
@@ -1040,45 +1026,6 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
 }
 
 
-/**
- * Take point from ECDH and convert it to key material.
- *
- * @param result point from ECDH
- * @param ctx ECC context
- * @param key_material[out] set to derived key material
- * @return #GNUNET_OK on success
- */
-static int
-point_to_hash (gcry_mpi_point_t result,
-               gcry_ctx_t ctx,
-               struct GNUNET_HashCode *key_material)
-{
-  gcry_mpi_t result_x;
-  unsigned char xbuf[256 / 8];
-  size_t rsize;
-
-  /* finally, convert point to string for hashing */
-  result_x = gcry_mpi_new (256);
-  if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
-    return GNUNET_SYSERR;
-  }
-
-  rsize = sizeof(xbuf);
-  GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
-  /* result_x can be negative here, so we do not use 
'GNUNET_CRYPTO_mpi_print_unsigned'
-     as that does not include the sign bit; x should be a 255-bit
-     value, so with the sign it should fit snugly into the 256-bit
-     xbuf */
-  GNUNET_assert (
-    0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
-  GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
-  gcry_mpi_release (result_x);
-  return GNUNET_OK;
-}
-
-
 /**
  * @ingroup crypto
  * Derive key material from a ECDH public key and a private EdDSA key.
@@ -1125,41 +1072,18 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *priv,
                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
                           struct GNUNET_HashCode *key_material)
 {
-  gcry_mpi_point_t result;
-  gcry_mpi_point_t q;
-  gcry_mpi_t d;
-  gcry_ctx_t ctx;
-  gcry_sexp_t pub_sexpr;
-  int ret;
+  uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
+  uint8_t d_rev[GNUNET_TWEETNACL_SCALARMULT_BYTES];
 
   BENCHMARK_START (ecdsa_ecdh);
-
-  /* first, extract the q = dP value from the public key */
-  if (0 != gcry_sexp_build (&pub_sexpr,
-                            NULL,
-                            "(public-key(ecc(curve " CURVE ")(q %b)))",
-                            (int) sizeof(pub->q_y),
-                            pub->q_y))
-    return GNUNET_SYSERR;
-  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
-  gcry_sexp_release (pub_sexpr);
-  q = gcry_mpi_ec_get_point ("q", ctx, 0);
-
-  /* second, extract the d value from our private key */
-  GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
-
-  /* then call the 'multiply' function, to compute the product */
-  result = gcry_mpi_point_new (0);
-  gcry_mpi_ec_mul (result, d, q, ctx);
-  gcry_mpi_point_release (q);
-  gcry_mpi_release (d);
-
-  /* finally, convert point to string for hashing */
-  ret = point_to_hash (result, ctx, key_material);
-  gcry_mpi_point_release (result);
-  gcry_ctx_release (ctx);
+  for (size_t i = 0; i < 32; i++)
+    d_rev[i] = priv->d[31 - i];
+  GNUNET_TWEETNACL_scalarmult_curve25519 (p, d_rev, pub->q_y);
+  GNUNET_CRYPTO_hash (p,
+                      GNUNET_TWEETNACL_SCALARMULT_BYTES,
+                      key_material);
   BENCHMARK_END (ecdsa_ecdh);
-  return ret;
+  return GNUNET_OK;
 }
 
 
@@ -1191,7 +1115,7 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct 
GNUNET_CRYPTO_EcdhePrivateKey *priv,
 /**
  * @ingroup crypto
  * Derive key material from a ECDSA public key and a private ECDH key.
- * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
+ * Dual to #GNUNET_CRYPTO_ecdsa_ecdh.
  *
  * @param priv private key to use for the ECDH (y)
  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
@@ -1203,10 +1127,13 @@ GNUNET_CRYPTO_ecdh_ecdsa (const struct 
GNUNET_CRYPTO_EcdhePrivateKey *priv,
                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
                           struct GNUNET_HashCode *key_material)
 {
-  return GNUNET_CRYPTO_ecdh_eddsa (priv,
-                                   (const struct GNUNET_CRYPTO_EddsaPublicKey 
*)
-                                   pub,
-                                   key_material);
+  uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
+  uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
+
+  GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
+  GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
+  GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
+  return GNUNET_OK;
 }
 
 
diff --git a/src/util/tweetnacl-gnunet.c b/src/util/tweetnacl-gnunet.c
index 1c27730a4..c3471ae66 100644
--- a/src/util/tweetnacl-gnunet.c
+++ b/src/util/tweetnacl-gnunet.c
@@ -424,8 +424,25 @@ GNUNET_TWEETNACL_sign_pk_from_seed (u8 *pk, const u8 *seed)
   d[31] &= 127;
   d[31] |= 64;
 
-  scalarbase (p,d);
-  pack (pk,p);
+  scalarbase (p, d);
+  pack (pk, p);
+}
+
+void
+GNUNET_TWEETNACL_scalarmult_le_ed25519_base (u8 *pk, const u8 *s)
+{
+  u8 d[64];
+  gf p[4];
+
+  // Treat s as little endian.
+  for (u32 i = 0; i < 32; i++)
+    d[i] = s[31 - i];
+  d[0] &= 248;
+  d[31] &= 127;
+  d[31] |= 64;
+
+  scalarbase (p, d);
+  pack (pk, p);
 }
 
 void
diff --git a/src/util/tweetnacl-gnunet.h b/src/util/tweetnacl-gnunet.h
index 239166ffc..2b2dc8e63 100644
--- a/src/util/tweetnacl-gnunet.h
+++ b/src/util/tweetnacl-gnunet.h
@@ -47,4 +47,8 @@ GNUNET_TWEETNACL_sign_detached (uint8_t *sig,
                                 const uint8_t *m,
                                 uint64_t n,
                                 const uint8_t *sk);
+
+void
+GNUNET_TWEETNACL_scalarmult_le_ed25519_base (uint8_t *pk, const uint8_t *s);
+
 #endif

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]