What changed, and why it matters
This commit only adds a new test file that exhaustively checks the ECDH (Elliptic Curve Diffie-Hellman) module. It does not change any production code, cryptographic logic, or build behavior for end users. There is no security vulnerability here; it is purely a test-suite improvement.
No security action needed. Treat as normal test-coverage improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds src/modules/ecdh/tests_exhaustive_impl.h and wires it into the build/test harness. The new test generates key pairs for all elements of the small exhaustive-test group, computes secp256k1_ecdh for every i,j pair, verifies symmetry, and recomputes the expected result manually using the default ECDH hash function on the precomputed group element. No implementation code is modified.
Changed components
src/modules/ecdh/tests_exhaustive_impl.h (new test file)src/modules/ecdh/Makefile.am.include (header registration)src/tests_exhaustive.c (test harness wiring)Inspect captured patch +64 / −0
diff --git a/src/modules/ecdh/Makefile.am.include b/src/modules/ecdh/Makefile.am.include
index 1866053..81bc627 100644
--- a/src/modules/ecdh/Makefile.am.include
+++ b/src/modules/ecdh/Makefile.am.include
@@ -1,5 +1,6 @@
include_HEADERS += include/secp256k1_ecdh.h
noinst_HEADERS += src/modules/ecdh/main_impl.h
noinst_HEADERS += src/modules/ecdh/tests_impl.h
+noinst_HEADERS += src/modules/ecdh/tests_exhaustive_impl.h
noinst_HEADERS += src/modules/ecdh/bench_impl.h
noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h
diff --git a/src/modules/ecdh/tests_exhaustive_impl.h b/src/modules/ecdh/tests_exhaustive_impl.h
new file mode 100644
index 0000000..2bcd243
--- /dev/null
+++ b/src/modules/ecdh/tests_exhaustive_impl.h
@@ -0,0 +1,56 @@
+/***********************************************************************
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
+ ***********************************************************************/
+
+#ifndef SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H
+#define SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H
+
+#include "../../../include/secp256k1_ecdh.h"
+#include "main_impl.h"
+
+static void test_exhaustive_ecdh(const secp256k1_context *ctx, const secp256k1_ge *group) {
+ int i, j;
+ unsigned char seckeys[EXHAUSTIVE_TEST_ORDER - 1][32];
+ secp256k1_pubkey pubkeys[EXHAUSTIVE_TEST_ORDER - 1];
+
+ /* Construct key pairs (32-byte secret key, public key object) for the entire group. */
+ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
+ secp256k1_scalar scalar;
+ secp256k1_scalar_set_int(&scalar, i);
+ secp256k1_scalar_get_b32(seckeys[i - 1], &scalar);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pubkeys[i - 1], seckeys[i - 1]));
+ }
+
+ /* Loop over key combinations. */
+ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
+ for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) {
+ unsigned char ecdh_result_ij[32];
+ unsigned char ecdh_result_ji[32];
+
+ /* Calculate ECDH(i*G, j) and ECDH(j*G, i) using API function and verify that the results match. */
+ CHECK(secp256k1_ecdh(ctx, ecdh_result_ij, &pubkeys[i - 1], seckeys[j - 1], NULL, NULL));
+ CHECK(secp256k1_ecdh(ctx, ecdh_result_ji, &pubkeys[j - 1], seckeys[i - 1], NULL, NULL));
+ CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_ji, 32) == 0);
+
+ /* Recalculate the expected ECDH result manually by invoking the default ECDH hash
+ * function on the precomputed group element (group[i * j]) coordinates, and verify
+ * that it matches the previously calculated public API results. */
+ {
+ secp256k1_ge ecdh_ge_expected = group[(i * j) % EXHAUSTIVE_TEST_ORDER];
+ unsigned char ecdh_result_expected[32];
+ unsigned char x[32];
+ unsigned char y[32];
+
+ secp256k1_fe_normalize_var(&ecdh_ge_expected.x);
+ secp256k1_fe_normalize_var(&ecdh_ge_expected.y);
+ secp256k1_fe_get_b32(x, &ecdh_ge_expected.x);
+ secp256k1_fe_get_b32(y, &ecdh_ge_expected.y);
+ CHECK(secp256k1_ecdh_hash_function_default(ecdh_result_expected, x, y, NULL));
+ CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_expected, 32) == 0);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
index 68d4bec..6d128bc 100644
--- a/src/tests_exhaustive.c
+++ b/src/tests_exhaustive.c
@@ -337,6 +337,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g
*/
}
+#ifdef ENABLE_MODULE_ECDH
+#include "modules/ecdh/tests_exhaustive_impl.h"
+#endif
+
#ifdef ENABLE_MODULE_RECOVERY
#include "modules/recovery/tests_exhaustive_impl.h"
#endif
@@ -437,6 +441,9 @@ int main(int argc, char** argv) {
test_exhaustive_sign(ctx, group);
test_exhaustive_verify(ctx, group);
+#ifdef ENABLE_MODULE_ECDH
+ test_exhaustive_ecdh(ctx, group);
+#endif
#ifdef ENABLE_MODULE_RECOVERY
test_exhaustive_recovery(ctx, group);
#endif
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.