diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2021-05-03 09:39:32 +0200 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2021-05-03 09:39:32 +0200 |
commit | 5831a14819679c841db1f7cbd78d42aef3f61b06 (patch) | |
tree | 356bd65c1f03d7689a4bdc7da983762a82a29352 | |
parent | cddd56b6c733d996e872783e7c54acf17135d11d (diff) |
-more comments, refactor derive_h
-rw-r--r-- | src/util/crypto_ecc_gnsrecord.c | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/src/util/crypto_ecc_gnsrecord.c b/src/util/crypto_ecc_gnsrecord.c index bab0ce44a..213f05863 100644 --- a/src/util/crypto_ecc_gnsrecord.c +++ b/src/util/crypto_ecc_gnsrecord.c @@ -42,20 +42,19 @@ * @param label label for deriviation * @param context additional context to use for HKDF of 'h'; * typically the name of the subsystem/application - * @return h value + * @param hc where to write the result */ -static gcry_mpi_t +void derive_h (const void *pub, size_t pubsize, const char *label, - const char *context) + const char *context, + struct GNUNET_HashCode *hc) { - gcry_mpi_t h; - struct GNUNET_HashCode hc; static const char *const salt = "key-derivation"; - GNUNET_CRYPTO_kdf (&hc, - sizeof(hc), + GNUNET_CRYPTO_kdf (hc, + sizeof(*hc), salt, strlen (salt), pub, @@ -66,8 +65,6 @@ derive_h (const void *pub, strlen (context), NULL, 0); - GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc)); - return h; } @@ -193,6 +190,7 @@ GNUNET_CRYPTO_ecdsa_private_key_derive ( { struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_CRYPTO_EcdsaPrivateKey *ret; + struct GNUNET_HashCode hc; uint8_t dc[32]; gcry_mpi_t h; gcry_mpi_t x; @@ -205,7 +203,9 @@ GNUNET_CRYPTO_ecdsa_private_key_derive ( n = gcry_mpi_ec_get_mpi ("n", ctx, 1); GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub); - h = derive_h (&pub, sizeof (pub), label, context); + derive_h (&pub, sizeof (pub), label, context, &hc); + GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc)); + /* Convert to big endian for libgcrypt */ for (size_t i = 0; i < 32; i++) dc[i] = priv->d[31 - i]; @@ -234,6 +234,7 @@ GNUNET_CRYPTO_ecdsa_public_key_derive ( const char *context, struct GNUNET_CRYPTO_EcdsaPublicKey *result) { + struct GNUNET_HashCode hc; gcry_ctx_t ctx; gcry_mpi_t q_y; gcry_mpi_t h; @@ -255,7 +256,8 @@ GNUNET_CRYPTO_ecdsa_public_key_derive ( GNUNET_assert (q); /* calculate h_mod_n = h % n */ - h = derive_h (pub, sizeof (pub), label, context); + derive_h (pub, sizeof (pub), label, context, &hc); + GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc)); n = gcry_mpi_ec_get_mpi ("n", ctx, 1); h_mod_n = gcry_mpi_new (256); gcry_mpi_mod (h_mod_n, h, n); @@ -286,6 +288,7 @@ GNUNET_CRYPTO_eddsa_private_key_derive ( struct GNUNET_CRYPTO_EddsaPrivateScalar *result) { struct GNUNET_CRYPTO_EddsaPublicKey pub; + struct GNUNET_HashCode hc; uint8_t dc[32]; unsigned char sk[64]; gcry_mpi_t h; @@ -297,20 +300,49 @@ GNUNET_CRYPTO_eddsa_private_key_derive ( gcry_mpi_t a2; gcry_ctx_t ctx; + /** + * Libsodium does not offer an API with arbitrary arithmetic. + * Hence we have to use libgcrypt here. + */ GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519")); + /** + * Get our modulo + */ n = gcry_mpi_ec_get_mpi ("n", ctx, 1); GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub); + + /** + * This is the standard private key expansion in Ed25519. + * The first 32 octets are used as a little-endian private + * scalar. + * We derive this scalar using our "h". + */ crypto_hash_sha512 (sk, priv->d, 32); sk[0] &= 248; sk[31] &= 127; sk[31] |= 64; - h = derive_h (&pub, sizeof (pub), label, context); + + /** + * Get h mod n + */ + derive_h (&pub, sizeof (pub), label, context, &hc); + GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc)); + h_mod_n = gcry_mpi_new (256); gcry_mpi_mod (h_mod_n, h, n); - /* Convert to big endian for libgcrypt */ + /* Convert scalar to big endian for libgcrypt */ for (size_t i = 0; i < 32; i++) dc[i] = sk[31 - i]; + + /** + * dc now contains the private scalar "a". + * We carefully remove the clamping and derive a'. + * Calculate: + * a1 := a / 8 + * a2 := h * a1 mod n + * a' := a2 * 8 mod n + */ GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc)); // a a1 = gcry_mpi_new (256); gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8); @@ -318,7 +350,6 @@ GNUNET_CRYPTO_eddsa_private_key_derive ( a2 = gcry_mpi_new (256); gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n d = gcry_mpi_new (256); - // gcry_mpi_mulm (d, a2, eight, n); // a' := a2 * 8 mod n gcry_mpi_mul (d, a2, eight); // a' := a2 * 8 gcry_mpi_release (h); gcry_mpi_release (x); @@ -327,10 +358,19 @@ GNUNET_CRYPTO_eddsa_private_key_derive ( gcry_mpi_release (a2); gcry_ctx_release (ctx); GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d); + /** + * Note that we copy all of SHA512(d) into the result and + * then overrwrite the derived private scalar. + * This means that we re-use SHA512(d)[32..63] + * FIXME: Do we want to derive this part as well?? + */ memcpy (result->s, sk, sizeof (sk)); /* Convert to little endian for libsodium */ for (size_t i = 0; i < 32; i++) result->s[i] = dc[31 - i]; + /** + * Clamp the scalar + */ result->s[0] &= 248; result->s[31] &= 127; result->s[31] |= 64; @@ -347,6 +387,7 @@ GNUNET_CRYPTO_eddsa_public_key_derive ( const char *context, struct GNUNET_CRYPTO_EddsaPublicKey *result) { + struct GNUNET_HashCode hc; gcry_ctx_t ctx; gcry_mpi_t q_y; gcry_mpi_t h; @@ -368,7 +409,9 @@ GNUNET_CRYPTO_eddsa_public_key_derive ( GNUNET_assert (q); /* calculate h_mod_n = h % n */ - h = derive_h (pub, sizeof (*pub), label, context); + derive_h (pub, sizeof (*pub), label, context, &hc); + GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc)); + n = gcry_mpi_ec_get_mpi ("n", ctx, 1); h_mod_n = gcry_mpi_new (256); gcry_mpi_mod (h_mod_n, h, n); |