[Pkg-bitcoin-commits] [libsecp256k1] 05/27: Add exhaustive test for verification

Jonas Smedegaard dr at jones.dk
Tue Jan 10 21:47:16 UTC 2017


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

js pushed a commit to branch master
in repository libsecp256k1.

commit b4ceedf14fbbbb0ddcf0f771090f94f9e3c2a21b
Author: Andrew Poelstra <apoelstra at wpsoftware.net>
Date:   Sat Apr 16 17:32:37 2016 +0000

    Add exhaustive test for verification
---
 src/ecdsa_impl.h       | 18 +++++++++++++++
 src/tests_exhaustive.c | 63 +++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h
index d110b4b..9a42e51 100644
--- a/src/ecdsa_impl.h
+++ b/src/ecdsa_impl.h
@@ -203,7 +203,9 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
 static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
     unsigned char c[32];
     secp256k1_scalar sn, u1, u2;
+#if !defined(EXHAUSTIVE_TEST_ORDER)
     secp256k1_fe xr;
+#endif
     secp256k1_gej pubkeyj;
     secp256k1_gej pr;
 
@@ -219,6 +221,21 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
     if (secp256k1_gej_is_infinity(&pr)) {
         return 0;
     }
+
+#if defined(EXHAUSTIVE_TEST_ORDER)
+{
+    secp256k1_scalar computed_r;
+    int overflow = 0;
+    secp256k1_ge pr_ge;
+    secp256k1_ge_set_gej(&pr_ge, &pr);
+    secp256k1_fe_normalize(&pr_ge.x);
+
+    secp256k1_fe_get_b32(c, &pr_ge.x);
+    secp256k1_scalar_set_b32(&computed_r, c, &overflow);
+    /* we fully expect overflow */
+    return secp256k1_scalar_eq(sigr, &computed_r);
+}
+#else
     secp256k1_scalar_get_b32(c, sigr);
     secp256k1_fe_set_b32(&xr, c);
 
@@ -252,6 +269,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
         return 1;
     }
     return 0;
+#endif
 }
 
 static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
index 3b88241..bda6ee4 100644
--- a/src/tests_exhaustive.c
+++ b/src/tests_exhaustive.c
@@ -1,4 +1,4 @@
-/**********************************************************************
+/***********************************************************************
  * Copyright (c) 2016 Andrew Poelstra                                 *
  * Distributed under the MIT software license, see the accompanying   *
  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
@@ -187,17 +187,54 @@ void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) {
     secp256k1_scalar_set_b32(r, x_bin, NULL);
 }
 
-/* hee hee hee */
-int solve_discrete_log(const secp256k1_scalar *x_coord, const secp256k1_ge *group, int order) {
-    int i;
-    for (i = 0; i < order; i++) {
-        secp256k1_scalar check_x;
-        r_from_k(&check_x, group, i);
-        if (*x_coord == check_x) {
-           return i;
+void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
+    int s, r, msg, key;
+    for (s = 1; s < order; s++) {
+        for (r = 1; r < order; r++) {
+            for (msg = 1; msg < order; msg++) {
+                for (key = 1; key < order; key++) {
+                    secp256k1_ge nonconst_ge;
+                    secp256k1_ecdsa_signature sig;
+                    secp256k1_pubkey pk;
+                    secp256k1_scalar sk_s, msg_s, r_s, s_s;
+                    secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s;
+                    int k, should_verify;
+                    unsigned char msg32[32];
+
+                    secp256k1_scalar_set_int(&s_s, s);
+                    secp256k1_scalar_set_int(&r_s, r);
+                    secp256k1_scalar_set_int(&msg_s, msg);
+                    secp256k1_scalar_set_int(&sk_s, key);
+
+                    /* Verify by hand */
+                    /* Run through every k value that gives us this r and check that *one* works.
+                     * Note there could be none, there could be multiple, ECDSA is weird. */
+                    should_verify = 0;
+                    for (k = 0; k < order; k++) {
+                        secp256k1_scalar check_x_s;
+                        r_from_k(&check_x_s, group, k);
+                        if (r_s == check_x_s) {
+                            secp256k1_scalar_set_int(&s_times_k_s, k);
+                            secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s);
+                            secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s);
+                            secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s);
+                            should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s);
+                        }
+                    }
+                    /* nb we have a "high s" rule */
+                    should_verify &= !secp256k1_scalar_is_high(&s_s);
+
+                    /* Verify by calling verify */
+                    secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s);
+                    memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge));
+                    secp256k1_pubkey_save(&pk, &nonconst_ge);
+                    secp256k1_scalar_get_b32(msg32, &msg_s);
+                    CHECK(should_verify ==
+                          secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk));
+                }
+            }
         }
     }
-    return -1;
 }
 
 void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
@@ -279,15 +316,13 @@ int main(void) {
     }
 
     /* Run the tests */
-    test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
-    /* cannot exhaustively test verify, since our verify code
-     * depends on the field order being less than twice the
-     * group order */
 #ifdef USE_ENDOMORPHISM
     test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER);
 #endif
     test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
     test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
+    test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
+    test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);
 
     return 0;
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libsecp256k1.git



More information about the Pkg-bitcoin-commits mailing list