Skip to content

Commit b4ceedf

Browse files
committed
Add exhaustive test for verification
1 parent 83836a9 commit b4ceedf

File tree

2 files changed

+67
-14
lines changed

2 files changed

+67
-14
lines changed

src/ecdsa_impl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
203203
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) {
204204
unsigned char c[32];
205205
secp256k1_scalar sn, u1, u2;
206+
#if !defined(EXHAUSTIVE_TEST_ORDER)
206207
secp256k1_fe xr;
208+
#endif
207209
secp256k1_gej pubkeyj;
208210
secp256k1_gej pr;
209211

@@ -219,6 +221,21 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
219221
if (secp256k1_gej_is_infinity(&pr)) {
220222
return 0;
221223
}
224+
225+
#if defined(EXHAUSTIVE_TEST_ORDER)
226+
{
227+
secp256k1_scalar computed_r;
228+
int overflow = 0;
229+
secp256k1_ge pr_ge;
230+
secp256k1_ge_set_gej(&pr_ge, &pr);
231+
secp256k1_fe_normalize(&pr_ge.x);
232+
233+
secp256k1_fe_get_b32(c, &pr_ge.x);
234+
secp256k1_scalar_set_b32(&computed_r, c, &overflow);
235+
/* we fully expect overflow */
236+
return secp256k1_scalar_eq(sigr, &computed_r);
237+
}
238+
#else
222239
secp256k1_scalar_get_b32(c, sigr);
223240
secp256k1_fe_set_b32(&xr, c);
224241

@@ -252,6 +269,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
252269
return 1;
253270
}
254271
return 0;
272+
#endif
255273
}
256274

257275
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) {

src/tests_exhaustive.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**********************************************************************
1+
/***********************************************************************
22
* Copyright (c) 2016 Andrew Poelstra *
33
* Distributed under the MIT software license, see the accompanying *
44
* 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) {
187187
secp256k1_scalar_set_b32(r, x_bin, NULL);
188188
}
189189

190-
/* hee hee hee */
191-
int solve_discrete_log(const secp256k1_scalar *x_coord, const secp256k1_ge *group, int order) {
192-
int i;
193-
for (i = 0; i < order; i++) {
194-
secp256k1_scalar check_x;
195-
r_from_k(&check_x, group, i);
196-
if (*x_coord == check_x) {
197-
return i;
190+
void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
191+
int s, r, msg, key;
192+
for (s = 1; s < order; s++) {
193+
for (r = 1; r < order; r++) {
194+
for (msg = 1; msg < order; msg++) {
195+
for (key = 1; key < order; key++) {
196+
secp256k1_ge nonconst_ge;
197+
secp256k1_ecdsa_signature sig;
198+
secp256k1_pubkey pk;
199+
secp256k1_scalar sk_s, msg_s, r_s, s_s;
200+
secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s;
201+
int k, should_verify;
202+
unsigned char msg32[32];
203+
204+
secp256k1_scalar_set_int(&s_s, s);
205+
secp256k1_scalar_set_int(&r_s, r);
206+
secp256k1_scalar_set_int(&msg_s, msg);
207+
secp256k1_scalar_set_int(&sk_s, key);
208+
209+
/* Verify by hand */
210+
/* Run through every k value that gives us this r and check that *one* works.
211+
* Note there could be none, there could be multiple, ECDSA is weird. */
212+
should_verify = 0;
213+
for (k = 0; k < order; k++) {
214+
secp256k1_scalar check_x_s;
215+
r_from_k(&check_x_s, group, k);
216+
if (r_s == check_x_s) {
217+
secp256k1_scalar_set_int(&s_times_k_s, k);
218+
secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s);
219+
secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s);
220+
secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s);
221+
should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s);
222+
}
223+
}
224+
/* nb we have a "high s" rule */
225+
should_verify &= !secp256k1_scalar_is_high(&s_s);
226+
227+
/* Verify by calling verify */
228+
secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s);
229+
memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge));
230+
secp256k1_pubkey_save(&pk, &nonconst_ge);
231+
secp256k1_scalar_get_b32(msg32, &msg_s);
232+
CHECK(should_verify ==
233+
secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk));
234+
}
235+
}
198236
}
199237
}
200-
return -1;
201238
}
202239

203240
void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
@@ -279,15 +316,13 @@ int main(void) {
279316
}
280317

281318
/* Run the tests */
282-
test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
283-
/* cannot exhaustively test verify, since our verify code
284-
* depends on the field order being less than twice the
285-
* group order */
286319
#ifdef USE_ENDOMORPHISM
287320
test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER);
288321
#endif
289322
test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
290323
test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
324+
test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
325+
test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);
291326

292327
return 0;
293328
}

0 commit comments

Comments
 (0)