]> Git Repo - secp256k1.git/blame - src/tests.c
Make pubkeys, set_xo, ... ge instead of gej
[secp256k1.git] / src / tests.c
CommitLineData
a41f32e6
PW
1#include <assert.h>
2
7a4b7691
PW
3#include "impl/num.h"
4#include "impl/field.h"
5#include "impl/group.h"
6#include "impl/ecmult.h"
7#include "impl/ecdsa.h"
d06e61cb 8#include "impl/util.h"
a41f32e6 9
404c30a8 10static int count = 100;
4adf6b2a 11
404c30a8
PW
12/***** NUM TESTS *****/
13
3f44e1ad
PW
14void random_num_negate(secp256k1_num_t *num) {
15 if (secp256k1_rand32() & 1)
16 secp256k1_num_negate(num);
17}
18
404c30a8 19void random_num_order_test(secp256k1_num_t *num) {
d06e61cb
PW
20 do {
21 unsigned char b32[32];
22 secp256k1_rand256_test(b32);
23 secp256k1_num_set_bin(num, b32, 32);
24 if (secp256k1_num_is_zero(num))
25 continue;
26 if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
27 continue;
28 break;
29 } while(1);
30}
31
404c30a8
PW
32void random_num_order(secp256k1_num_t *num) {
33 do {
34 unsigned char b32[32];
35 secp256k1_rand256(b32);
36 secp256k1_num_set_bin(num, b32, 32);
37 if (secp256k1_num_is_zero(num))
38 continue;
39 if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
40 continue;
41 break;
42 } while(1);
43}
44
45void test_num_copy_inc_cmp() {
46 secp256k1_num_t n1,n2;
47 secp256k1_num_init(&n1);
48 secp256k1_num_init(&n2);
49 random_num_order(&n1);
50 secp256k1_num_copy(&n2, &n1);
51 assert(secp256k1_num_cmp(&n1, &n2) == 0);
52 assert(secp256k1_num_cmp(&n2, &n1) == 0);
53 secp256k1_num_inc(&n2);
54 assert(secp256k1_num_cmp(&n1, &n2) != 0);
55 assert(secp256k1_num_cmp(&n2, &n1) != 0);
56 secp256k1_num_free(&n1);
57 secp256k1_num_free(&n2);
58}
59
404c30a8
PW
60
61void test_num_get_set_hex() {
62 secp256k1_num_t n1,n2;
63 secp256k1_num_init(&n1);
64 secp256k1_num_init(&n2);
65 random_num_order_test(&n1);
66 char c[64];
67 secp256k1_num_get_hex(c, 64, &n1);
68 secp256k1_num_set_hex(&n2, c, 64);
69 assert(secp256k1_num_cmp(&n1, &n2) == 0);
70 for (int i=0; i<64; i++) {
71 // check whether the lower 4 bits correspond to the last hex character
72 int low1 = secp256k1_num_shift(&n1, 4);
73 int lowh = c[63];
74 int low2 = (lowh>>6)*9+(lowh-'0')&15;
75 assert(low1 == low2);
76 // shift bits off the hex representation, and compare
77 memmove(c+1, c, 63);
78 c[0] = '0';
79 secp256k1_num_set_hex(&n2, c, 64);
80 assert(secp256k1_num_cmp(&n1, &n2) == 0);
81 }
82 secp256k1_num_free(&n2);
83 secp256k1_num_free(&n1);
84}
85
86void test_num_get_set_bin() {
87 secp256k1_num_t n1,n2;
88 secp256k1_num_init(&n1);
89 secp256k1_num_init(&n2);
90 random_num_order_test(&n1);
91 unsigned char c[32];
92 secp256k1_num_get_bin(c, 32, &n1);
93 secp256k1_num_set_bin(&n2, c, 32);
94 assert(secp256k1_num_cmp(&n1, &n2) == 0);
95 for (int i=0; i<32; i++) {
96 // check whether the lower 8 bits correspond to the last byte
97 int low1 = secp256k1_num_shift(&n1, 8);
98 int low2 = c[31];
99 assert(low1 == low2);
100 // shift bits off the byte representation, and compare
101 memmove(c+1, c, 31);
102 c[0] = 0;
103 secp256k1_num_set_bin(&n2, c, 32);
104 assert(secp256k1_num_cmp(&n1, &n2) == 0);
105 }
106 secp256k1_num_free(&n2);
107 secp256k1_num_free(&n1);
108}
109
404c30a8
PW
110void run_num_int() {
111 secp256k1_num_t n1;
112 secp256k1_num_init(&n1);
113 for (int i=-255; i<256; i++) {
114 unsigned char c1[3] = {};
115 c1[2] = abs(i);
116 unsigned char c2[3] = {0x11,0x22,0x33};
117 secp256k1_num_set_int(&n1, i);
118 secp256k1_num_get_bin(c2, 3, &n1);
119 assert(memcmp(c1, c2, 3) == 0);
120 }
121 secp256k1_num_free(&n1);
122}
123
3f44e1ad
PW
124void test_num_negate() {
125 secp256k1_num_t n1;
126 secp256k1_num_t n2;
127 secp256k1_num_init(&n1);
128 secp256k1_num_init(&n2);
129 random_num_order_test(&n1); // n1 = R
130 random_num_negate(&n1);
131 secp256k1_num_copy(&n2, &n1); // n2 = R
132 secp256k1_num_sub(&n1, &n2, &n1); // n1 = n2-n1 = 0
133 assert(secp256k1_num_is_zero(&n1));
134 secp256k1_num_copy(&n1, &n2); // n1 = R
135 secp256k1_num_negate(&n1); // n1 = -R
136 assert(!secp256k1_num_is_zero(&n1));
137 secp256k1_num_add(&n1, &n2, &n1); // n1 = n2+n1 = 0
138 assert(secp256k1_num_is_zero(&n1));
139 secp256k1_num_copy(&n1, &n2); // n1 = R
140 secp256k1_num_negate(&n1); // n1 = -R
141 assert(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2));
142 secp256k1_num_negate(&n1); // n1 = R
143 assert(secp256k1_num_cmp(&n1, &n2) == 0);
144 assert(secp256k1_num_is_neg(&n1) == secp256k1_num_is_neg(&n2));
145 secp256k1_num_free(&n2);
146 secp256k1_num_free(&n1);
147}
148
149void test_num_add_sub() {
150 secp256k1_num_t n1;
151 secp256k1_num_t n2;
152 secp256k1_num_init(&n1);
153 secp256k1_num_init(&n2);
154 random_num_order_test(&n1); // n1 = R1
155 random_num_negate(&n1);
156 random_num_order_test(&n2); // n2 = R2
157 random_num_negate(&n2);
158 secp256k1_num_t n1p2, n2p1, n1m2, n2m1;
159 secp256k1_num_init(&n1p2);
160 secp256k1_num_init(&n2p1);
161 secp256k1_num_init(&n1m2);
162 secp256k1_num_init(&n2m1);
163 secp256k1_num_add(&n1p2, &n1, &n2); // n1p2 = R1 + R2
164 secp256k1_num_add(&n2p1, &n2, &n1); // n2p1 = R2 + R1
165 secp256k1_num_sub(&n1m2, &n1, &n2); // n1m2 = R1 - R2
166 secp256k1_num_sub(&n2m1, &n2, &n1); // n2m1 = R2 - R1
167 assert(secp256k1_num_cmp(&n1p2, &n2p1) == 0);
168 assert(secp256k1_num_cmp(&n1p2, &n1m2) != 0);
169 secp256k1_num_negate(&n2m1); // n2m1 = -R2 + R1
170 assert(secp256k1_num_cmp(&n2m1, &n1m2) == 0);
171 assert(secp256k1_num_cmp(&n2m1, &n1) != 0);
172 secp256k1_num_add(&n2m1, &n2m1, &n2); // n2m1 = -R2 + R1 + R2 = R1
173 assert(secp256k1_num_cmp(&n2m1, &n1) == 0);
174 assert(secp256k1_num_cmp(&n2p1, &n1) != 0);
175 secp256k1_num_sub(&n2p1, &n2p1, &n2); // n2p1 = R2 + R1 - R2 = R1
176 assert(secp256k1_num_cmp(&n2p1, &n1) == 0);
177 secp256k1_num_free(&n2m1);
178 secp256k1_num_free(&n1m2);
179 secp256k1_num_free(&n2p1);
180 secp256k1_num_free(&n1p2);
181 secp256k1_num_free(&n2);
182 secp256k1_num_free(&n1);
183}
184
185void run_num_smalltests() {
186 for (int i=0; i<100*count; i++) {
187 test_num_copy_inc_cmp();
188 test_num_get_set_hex();
189 test_num_get_set_bin();
190 test_num_negate();
191 test_num_add_sub();
192 }
193 run_num_int();
194}
195
404c30a8 196void run_ecmult_chain() {
cbd3617e 197 // random starting point A (on the curve)
910d0de4
PW
198 secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64);
199 secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
f11ff5be 200 secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
cbd3617e 201 // two random initial factors xn and gn
4adf6b2a
PW
202 secp256k1_num_t xn;
203 secp256k1_num_init(&xn);
204 secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
205 secp256k1_num_t gn;
206 secp256k1_num_init(&gn);
207 secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
cbd3617e 208 // two small multipliers to be applied to xn and gn in every iteration:
4adf6b2a
PW
209 secp256k1_num_t xf;
210 secp256k1_num_init(&xf);
211 secp256k1_num_set_hex(&xf, "1337", 4);
212 secp256k1_num_t gf;
213 secp256k1_num_init(&gf);
214 secp256k1_num_set_hex(&gf, "7113", 4);
cbd3617e 215 // accumulators with the resulting coefficients to A and G
4adf6b2a
PW
216 secp256k1_num_t ae;
217 secp256k1_num_init(&ae);
218 secp256k1_num_set_int(&ae, 1);
219 secp256k1_num_t ge;
220 secp256k1_num_init(&ge);
221 secp256k1_num_set_int(&ge, 0);
cbd3617e 222 // the point being computed
f11ff5be
PW
223 secp256k1_gej_t x = a;
224 const secp256k1_num_t *order = &secp256k1_ge_consts->order;
404c30a8 225 for (int i=0; i<200*count; i++) {
14b195ee 226 // in each iteration, compute X = xn*X + gn*G;
b1483f87 227 secp256k1_ecmult(&x, &x, &xn, &gn);
14b195ee
PW
228 // also compute ae and ge: the actual accumulated factors for A and G
229 // if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
f11ff5be
PW
230 secp256k1_num_mod_mul(&ae, &ae, &xn, order);
231 secp256k1_num_mod_mul(&ge, &ge, &xn, order);
4adf6b2a 232 secp256k1_num_add(&ge, &ge, &gn);
2f9e831d 233 secp256k1_num_mod(&ge, order);
14b195ee 234 // modify xn and gn
f11ff5be
PW
235 secp256k1_num_mod_mul(&xn, &xn, &xf, order);
236 secp256k1_num_mod_mul(&gn, &gn, &gf, order);
404c30a8
PW
237
238 // verify
239 if (i == 19999) {
240 char res[132]; int resl = 132;
241 secp256k1_gej_get_hex(res, &resl, &x);
242 assert(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
243 }
4adf6b2a 244 }
14b195ee 245 // redo the computation, but directly with the resulting ae and ge coefficients:
b1483f87 246 secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge);
404c30a8 247 char res[132]; int resl = 132;
f11ff5be 248 char res2[132]; int resl2 = 132;
404c30a8 249 secp256k1_gej_get_hex(res, &resl, &x);
f11ff5be
PW
250 secp256k1_gej_get_hex(res2, &resl2, &x2);
251 assert(strcmp(res, res2) == 0);
252 assert(strlen(res) == 131);
4adf6b2a
PW
253 secp256k1_num_free(&xn);
254 secp256k1_num_free(&gn);
255 secp256k1_num_free(&xf);
256 secp256k1_num_free(&gf);
257 secp256k1_num_free(&ae);
258 secp256k1_num_free(&ge);
a41f32e6
PW
259}
260
eb0be8ee 261void test_point_times_order(const secp256k1_gej_t *point) {
4e0ed539 262 // either the point is not on the curve, or multiplying it by the order results in O
eb0be8ee 263 if (!secp256k1_gej_is_valid(point))
4e0ed539
PW
264 return;
265
f11ff5be 266 const secp256k1_num_t *order = &secp256k1_ge_consts->order;
4adf6b2a
PW
267 secp256k1_num_t zero;
268 secp256k1_num_init(&zero);
269 secp256k1_num_set_int(&zero, 0);
f11ff5be 270 secp256k1_gej_t res;
eb0be8ee 271 secp256k1_ecmult(&res, point, order, order); // calc res = order * point + order * G;
f11ff5be 272 assert(secp256k1_gej_is_infinity(&res));
4adf6b2a 273 secp256k1_num_free(&zero);
4e0ed539
PW
274}
275
404c30a8 276void run_point_times_order() {
910d0de4 277 secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2);
4e0ed539 278 for (int i=0; i<500; i++) {
764332d0
PW
279 secp256k1_ge_t p; secp256k1_ge_set_xo(&p, &x, 1);
280 secp256k1_gej_t j; secp256k1_gej_set_ge(&j, &p);
eb0be8ee 281 test_point_times_order(&j);
910d0de4 282 secp256k1_fe_sqr(&x, &x);
4e0ed539 283 }
910d0de4
PW
284 char c[65]; int cl=65;
285 secp256k1_fe_get_hex(c, &cl, &x);
286 assert(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
4e0ed539
PW
287}
288
eb0be8ee 289void test_wnaf(const secp256k1_num_t *number, int w) {
4adf6b2a
PW
290 secp256k1_num_t x, two, t;
291 secp256k1_num_init(&x);
292 secp256k1_num_init(&two);
293 secp256k1_num_init(&t);
294 secp256k1_num_set_int(&x, 0);
295 secp256k1_num_set_int(&two, 2);
898cecb3 296 int wnaf[257];
eb0be8ee 297 int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
4e0ed539 298 int zeroes = -1;
b1483f87 299 for (int i=bits-1; i>=0; i--) {
4adf6b2a 300 secp256k1_num_mul(&x, &x, &two);
b1483f87 301 int v = wnaf[i];
4e0ed539
PW
302 if (v) {
303 assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
304 zeroes=0;
305 assert((v & 1) == 1); // check non-zero elements are odd
306 assert(v <= (1 << (w-1)) - 1); // check range below
307 assert(v >= -(1 << (w-1)) - 1); // check range above
308 } else {
309 assert(zeroes != -1); // check that no unnecessary zero padding exists
310 zeroes++;
311 }
4adf6b2a
PW
312 secp256k1_num_set_int(&t, v);
313 secp256k1_num_add(&x, &x, &t);
4e0ed539 314 }
eb0be8ee 315 assert(secp256k1_num_cmp(&x, number) == 0); // check that wnaf represents number
4adf6b2a
PW
316 secp256k1_num_free(&x);
317 secp256k1_num_free(&two);
318 secp256k1_num_free(&t);
4e0ed539
PW
319}
320
404c30a8 321void run_wnaf() {
d06e61cb 322 secp256k1_num_t n;
4adf6b2a 323 secp256k1_num_init(&n);
404c30a8 324 for (int i=0; i<count; i++) {
d06e61cb
PW
325 random_num_order(&n);
326 if (i % 1)
327 secp256k1_num_negate(&n);
eb0be8ee 328 test_wnaf(&n, 4+(i%10));
4e0ed539 329 }
4adf6b2a 330 secp256k1_num_free(&n);
4e0ed539 331}
a41f32e6 332
0a07e62f 333void test_ecdsa_sign_verify() {
eb0be8ee 334 const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
4adf6b2a
PW
335 secp256k1_num_t msg, key, nonce;
336 secp256k1_num_init(&msg);
404c30a8 337 random_num_order_test(&msg);
4adf6b2a 338 secp256k1_num_init(&key);
404c30a8 339 random_num_order_test(&key);
4adf6b2a 340 secp256k1_num_init(&nonce);
764332d0
PW
341 secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key);
342 secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
d41e93a5
PW
343 secp256k1_ecdsa_sig_t sig;
344 secp256k1_ecdsa_sig_init(&sig);
0a07e62f 345 do {
404c30a8 346 random_num_order_test(&nonce);
d41e93a5
PW
347 } while(!secp256k1_ecdsa_sig_sign(&sig, &key, &msg, &nonce));
348 assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
4adf6b2a 349 secp256k1_num_inc(&msg);
d41e93a5
PW
350 assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
351 secp256k1_ecdsa_sig_free(&sig);
4adf6b2a
PW
352 secp256k1_num_free(&msg);
353 secp256k1_num_free(&key);
354 secp256k1_num_free(&nonce);
0a07e62f
PW
355}
356
404c30a8
PW
357void run_ecdsa_sign_verify() {
358 for (int i=0; i<10*count; i++) {
0a07e62f
PW
359 test_ecdsa_sign_verify();
360 }
361}
362
404c30a8
PW
363int main(int argc, char **argv) {
364 if (argc > 1)
3f44e1ad 365 count = strtol(argv[1], NULL, 0)*47;
404c30a8
PW
366
367 // initialize
910d0de4 368 secp256k1_fe_start();
f11ff5be 369 secp256k1_ge_start();
b1483f87 370 secp256k1_ecmult_start();
4adf6b2a 371
404c30a8 372 // num tests
3f44e1ad 373 run_num_smalltests();
404c30a8
PW
374
375 // ecmult tests
376 run_wnaf();
377 run_point_times_order();
378 run_ecmult_chain();
379
380 // ecdsa tests
381 run_ecdsa_sign_verify();
910d0de4 382
404c30a8 383 // shutdown
b1483f87 384 secp256k1_ecmult_stop();
f11ff5be 385 secp256k1_ge_stop();
910d0de4 386 secp256k1_fe_stop();
a41f32e6
PW
387 return 0;
388}
This page took 0.071017 seconds and 4 git commands to generate.