From 0fae6db267363a9cfc1a763fc50afae641e720da Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Wed, 7 Dec 2022 19:39:02 +0100 Subject: [PATCH] Less error prone EdDSA verification building blocks crypto_eddsa_r_check() is replaced by crypto_eddsa_check_equation(). This has two advantages: - Users now only need to return the value of crypto_eddsa_r_check(). No need for an additional check we may forget, much safer. - Verifying the equation give better optimisation opportunities. --- src/monocypher.c | 32 ++++++++++++------------------- src/monocypher.h | 8 +++----- src/optional/monocypher-ed25519.c | 6 +----- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/monocypher.c b/src/monocypher.c index e603b73..3c0bf96 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -2218,20 +2218,21 @@ void crypto_eddsa_scalarbase(u8 point[32], const u8 scalar[32]) WIPE_CTX(&P); } -int crypto_eddsa_r_check(u8 r_check[32], const u8 public_key[32], - const u8 h_ram[32], const u8 s[32]) +int crypto_eddsa_check_equation(const u8 signature[64], const u8 public_key[32], + const u8 h_ram[32]) { ge A; + const u8 *s = signature + 32; u32 s32[8]; // s (different encoding) load32_le_buf(s32, s, 8); - if (ge_frombytes_neg_vartime(&A, public_key) || // A = -pk is_above_l(s32)) { // prevent s malleability return -1; } ge_double_scalarmult_vartime(&A, h_ram, s); // A = [s]B - [h_ram]pk + u8 r_check[32]; ge_tobytes(r_check, &A); // r_check = A - return 0; + return crypto_verify32(r_check, signature); // R == R_check ? OK : fail } void crypto_eddsa_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32]) @@ -2337,29 +2338,20 @@ void crypto_eddsa_sign(u8 signature [64], const u8 secret_key[32], WIPE_BUFFER(r); } -// To verify a signature, there are 3 steps: -// -// S, R = signature -// h = HASH(R || public_key || message) % L -// R' = [s]B - [h]public_key +// To check the signature R, S of the message M with the public key A, +// there are 3 steps: // -// For the signature to be valid, **TWO** conditions must hold: +// compute h = HASH(R || A || message) % L +// check that A is on the curve. +// check that R == [s]B - [h]A // -// - Computing R' must succeed. -// - R and R' must be identical (duh). -// -// Don't you **ever** forget to check the return value of -// `crypto_eddsa_r_check()`. +// The last two steps are done in crypto_eddsa_check_equation() int crypto_eddsa_check(const u8 signature[64], const u8 public_key[32], const u8 *message, size_t message_size) { u8 h_ram [32]; - u8 r_check[32]; hash_reduce(h_ram, signature, 32, public_key, 32, message, message_size); - if (crypto_eddsa_r_check(r_check, public_key, h_ram, signature + 32)) { - return -1; - } - return crypto_verify32(r_check, signature); // R == R_check ? OK : fail + return crypto_eddsa_check_equation(signature, public_key, h_ram); } /////////////////////// diff --git a/src/monocypher.h b/src/monocypher.h index 7a25a0a..941fa04 100644 --- a/src/monocypher.h +++ b/src/monocypher.h @@ -289,11 +289,9 @@ void crypto_eddsa_mul_add(uint8_t r[32], const uint8_t b[32], const uint8_t c[32]); void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]); -int crypto_eddsa_r_check(uint8_t r_check[32], - const uint8_t public_key[32], - const uint8_t h_ram[32], - const uint8_t s[32]); - +int crypto_eddsa_check_equation(const uint8_t signature[64], + const uint8_t public_key[32], + const uint8_t h_ram[32]); // EdDSA to X25519 // --------------- diff --git a/src/optional/monocypher-ed25519.c b/src/optional/monocypher-ed25519.c index ec9d441..4602615 100644 --- a/src/optional/monocypher-ed25519.c +++ b/src/optional/monocypher-ed25519.c @@ -390,12 +390,8 @@ int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32], const u8 *message, size_t message_size) { u8 h_ram [32]; - u8 r_check[32]; hash_reduce(h_ram, signature, 32, public_key, 32, message, message_size); - if (crypto_eddsa_r_check(r_check, public_key, h_ram, signature + 32)) { - return -1; - } - return crypto_verify32(r_check, signature); // R == R_check ? OK : fail + return crypto_eddsa_check_equation(signature, public_key, h_ram); } void crypto_from_ed25519_private(u8 x25519[32], const u8 eddsa[32]) -- 2.47.3