|
|
|
@ -6,8 +6,8 @@
|
|
|
|
|
#include "libsecp256k1-config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include "num_impl.h"
|
|
|
|
|
#include "field_impl.h"
|
|
|
|
@ -23,6 +23,13 @@
|
|
|
|
|
#include "openssl/obj_mac.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define TEST_FAILURE(msg) do { \
|
|
|
|
|
fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \
|
|
|
|
|
abort(); \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
#define CHECK(cond) do { if (!(cond)) { TEST_FAILURE("test condition failed: " #cond); } } while(0)
|
|
|
|
|
|
|
|
|
|
static int count = 100;
|
|
|
|
|
|
|
|
|
|
/***** NUM TESTS *****/
|
|
|
|
@ -64,11 +71,11 @@ void test_num_copy_inc_cmp() {
|
|
|
|
|
secp256k1_num_init(&n2);
|
|
|
|
|
random_num_order(&n1);
|
|
|
|
|
secp256k1_num_copy(&n2, &n1);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
assert(secp256k1_num_cmp(&n2, &n1) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2, &n1) == 0);
|
|
|
|
|
secp256k1_num_inc(&n2);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) != 0);
|
|
|
|
|
assert(secp256k1_num_cmp(&n2, &n1) != 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) != 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2, &n1) != 0);
|
|
|
|
|
secp256k1_num_free(&n1);
|
|
|
|
|
secp256k1_num_free(&n2);
|
|
|
|
|
}
|
|
|
|
@ -82,18 +89,18 @@ void test_num_get_set_hex() {
|
|
|
|
|
char c[64];
|
|
|
|
|
secp256k1_num_get_hex(c, 64, &n1);
|
|
|
|
|
secp256k1_num_set_hex(&n2, c, 64);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
for (int i=0; i<64; i++) {
|
|
|
|
|
// check whether the lower 4 bits correspond to the last hex character
|
|
|
|
|
int low1 = secp256k1_num_shift(&n1, 4);
|
|
|
|
|
int lowh = c[63];
|
|
|
|
|
int low2 = (lowh>>6)*9+(lowh-'0')&15;
|
|
|
|
|
assert(low1 == low2);
|
|
|
|
|
CHECK(low1 == low2);
|
|
|
|
|
// shift bits off the hex representation, and compare
|
|
|
|
|
memmove(c+1, c, 63);
|
|
|
|
|
c[0] = '0';
|
|
|
|
|
secp256k1_num_set_hex(&n2, c, 64);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
}
|
|
|
|
|
secp256k1_num_free(&n2);
|
|
|
|
|
secp256k1_num_free(&n1);
|
|
|
|
@ -107,17 +114,17 @@ void test_num_get_set_bin() {
|
|
|
|
|
unsigned char c[32];
|
|
|
|
|
secp256k1_num_get_bin(c, 32, &n1);
|
|
|
|
|
secp256k1_num_set_bin(&n2, c, 32);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
for (int i=0; i<32; i++) {
|
|
|
|
|
// check whether the lower 8 bits correspond to the last byte
|
|
|
|
|
int low1 = secp256k1_num_shift(&n1, 8);
|
|
|
|
|
int low2 = c[31];
|
|
|
|
|
assert(low1 == low2);
|
|
|
|
|
CHECK(low1 == low2);
|
|
|
|
|
// shift bits off the byte representation, and compare
|
|
|
|
|
memmove(c+1, c, 31);
|
|
|
|
|
c[0] = 0;
|
|
|
|
|
secp256k1_num_set_bin(&n2, c, 32);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
}
|
|
|
|
|
secp256k1_num_free(&n2);
|
|
|
|
|
secp256k1_num_free(&n1);
|
|
|
|
@ -132,7 +139,7 @@ void run_num_int() {
|
|
|
|
|
unsigned char c2[3] = {0x11,0x22,0x33};
|
|
|
|
|
secp256k1_num_set_int(&n1, i);
|
|
|
|
|
secp256k1_num_get_bin(c2, 3, &n1);
|
|
|
|
|
assert(memcmp(c1, c2, 3) == 0);
|
|
|
|
|
CHECK(memcmp(c1, c2, 3) == 0);
|
|
|
|
|
}
|
|
|
|
|
secp256k1_num_free(&n1);
|
|
|
|
|
}
|
|
|
|
@ -146,18 +153,18 @@ void test_num_negate() {
|
|
|
|
|
random_num_negate(&n1);
|
|
|
|
|
secp256k1_num_copy(&n2, &n1); // n2 = R
|
|
|
|
|
secp256k1_num_sub(&n1, &n2, &n1); // n1 = n2-n1 = 0
|
|
|
|
|
assert(secp256k1_num_is_zero(&n1));
|
|
|
|
|
CHECK(secp256k1_num_is_zero(&n1));
|
|
|
|
|
secp256k1_num_copy(&n1, &n2); // n1 = R
|
|
|
|
|
secp256k1_num_negate(&n1); // n1 = -R
|
|
|
|
|
assert(!secp256k1_num_is_zero(&n1));
|
|
|
|
|
CHECK(!secp256k1_num_is_zero(&n1));
|
|
|
|
|
secp256k1_num_add(&n1, &n2, &n1); // n1 = n2+n1 = 0
|
|
|
|
|
assert(secp256k1_num_is_zero(&n1));
|
|
|
|
|
CHECK(secp256k1_num_is_zero(&n1));
|
|
|
|
|
secp256k1_num_copy(&n1, &n2); // n1 = R
|
|
|
|
|
secp256k1_num_negate(&n1); // n1 = -R
|
|
|
|
|
assert(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2));
|
|
|
|
|
CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2));
|
|
|
|
|
secp256k1_num_negate(&n1); // n1 = R
|
|
|
|
|
assert(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
assert(secp256k1_num_is_neg(&n1) == secp256k1_num_is_neg(&n2));
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1, &n2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_is_neg(&n1) == secp256k1_num_is_neg(&n2));
|
|
|
|
|
secp256k1_num_free(&n2);
|
|
|
|
|
secp256k1_num_free(&n1);
|
|
|
|
|
}
|
|
|
|
@ -180,16 +187,16 @@ void test_num_add_sub() {
|
|
|
|
|
secp256k1_num_add(&n2p1, &n2, &n1); // n2p1 = R2 + R1
|
|
|
|
|
secp256k1_num_sub(&n1m2, &n1, &n2); // n1m2 = R1 - R2
|
|
|
|
|
secp256k1_num_sub(&n2m1, &n2, &n1); // n2m1 = R2 - R1
|
|
|
|
|
assert(secp256k1_num_cmp(&n1p2, &n2p1) == 0);
|
|
|
|
|
assert(secp256k1_num_cmp(&n1p2, &n1m2) != 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1p2, &n2p1) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n1p2, &n1m2) != 0);
|
|
|
|
|
secp256k1_num_negate(&n2m1); // n2m1 = -R2 + R1
|
|
|
|
|
assert(secp256k1_num_cmp(&n2m1, &n1m2) == 0);
|
|
|
|
|
assert(secp256k1_num_cmp(&n2m1, &n1) != 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2m1, &n1m2) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2m1, &n1) != 0);
|
|
|
|
|
secp256k1_num_add(&n2m1, &n2m1, &n2); // n2m1 = -R2 + R1 + R2 = R1
|
|
|
|
|
assert(secp256k1_num_cmp(&n2m1, &n1) == 0);
|
|
|
|
|
assert(secp256k1_num_cmp(&n2p1, &n1) != 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2m1, &n1) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2p1, &n1) != 0);
|
|
|
|
|
secp256k1_num_sub(&n2p1, &n2p1, &n2); // n2p1 = R2 + R1 - R2 = R1
|
|
|
|
|
assert(secp256k1_num_cmp(&n2p1, &n1) == 0);
|
|
|
|
|
CHECK(secp256k1_num_cmp(&n2p1, &n1) == 0);
|
|
|
|
|
secp256k1_num_free(&n2m1);
|
|
|
|
|
secp256k1_num_free(&n1m2);
|
|
|
|
|
secp256k1_num_free(&n2p1);
|
|
|
|
@ -226,7 +233,7 @@ void random_fe_non_zero(secp256k1_fe_t *nz) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// Infinitesimal probability of spurious failure here
|
|
|
|
|
assert(tries >= 0);
|
|
|
|
|
CHECK(tries >= 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void random_fe_non_square(secp256k1_fe_t *ns) {
|
|
|
|
@ -240,14 +247,14 @@ void random_fe_non_square(secp256k1_fe_t *ns) {
|
|
|
|
|
void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) {
|
|
|
|
|
secp256k1_fe_t r1, r2;
|
|
|
|
|
int v = secp256k1_fe_sqrt(&r1, a);
|
|
|
|
|
assert((v == 0) == (k == NULL));
|
|
|
|
|
CHECK((v == 0) == (k == NULL));
|
|
|
|
|
|
|
|
|
|
if (k != NULL) {
|
|
|
|
|
// Check that the returned root is +/- the given known answer
|
|
|
|
|
secp256k1_fe_negate(&r2, &r1, 1);
|
|
|
|
|
secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k);
|
|
|
|
|
secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2);
|
|
|
|
|
assert(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2));
|
|
|
|
|
CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -331,7 +338,7 @@ void run_ecmult_chain() {
|
|
|
|
|
if (i == 19999) {
|
|
|
|
|
char res[132]; int resl = 132;
|
|
|
|
|
secp256k1_gej_get_hex(res, &resl, &x);
|
|
|
|
|
assert(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
|
|
|
|
|
CHECK(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// redo the computation, but directly with the resulting ae and ge coefficients:
|
|
|
|
@ -340,8 +347,8 @@ void run_ecmult_chain() {
|
|
|
|
|
char res2[132]; int resl2 = 132;
|
|
|
|
|
secp256k1_gej_get_hex(res, &resl, &x);
|
|
|
|
|
secp256k1_gej_get_hex(res2, &resl2, &x2);
|
|
|
|
|
assert(strcmp(res, res2) == 0);
|
|
|
|
|
assert(strlen(res) == 131);
|
|
|
|
|
CHECK(strcmp(res, res2) == 0);
|
|
|
|
|
CHECK(strlen(res) == 131);
|
|
|
|
|
secp256k1_num_free(&xn);
|
|
|
|
|
secp256k1_num_free(&gn);
|
|
|
|
|
secp256k1_num_free(&xf);
|
|
|
|
@ -358,7 +365,7 @@ void test_point_times_order(const secp256k1_gej_t *point) {
|
|
|
|
|
secp256k1_num_set_int(&zero, 0);
|
|
|
|
|
secp256k1_gej_t res;
|
|
|
|
|
secp256k1_ecmult(&res, point, order, order); // calc res = order * point + order * G;
|
|
|
|
|
assert(secp256k1_gej_is_infinity(&res));
|
|
|
|
|
CHECK(secp256k1_gej_is_infinity(&res));
|
|
|
|
|
secp256k1_num_free(&zero);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -367,17 +374,17 @@ void run_point_times_order() {
|
|
|
|
|
for (int i=0; i<500; i++) {
|
|
|
|
|
secp256k1_ge_t p;
|
|
|
|
|
if (secp256k1_ge_set_xo(&p, &x, 1)) {
|
|
|
|
|
assert(secp256k1_ge_is_valid(&p));
|
|
|
|
|
CHECK(secp256k1_ge_is_valid(&p));
|
|
|
|
|
secp256k1_gej_t j;
|
|
|
|
|
secp256k1_gej_set_ge(&j, &p);
|
|
|
|
|
assert(secp256k1_gej_is_valid(&j));
|
|
|
|
|
CHECK(secp256k1_gej_is_valid(&j));
|
|
|
|
|
test_point_times_order(&j);
|
|
|
|
|
}
|
|
|
|
|
secp256k1_fe_sqr(&x, &x);
|
|
|
|
|
}
|
|
|
|
|
char c[65]; int cl=65;
|
|
|
|
|
secp256k1_fe_get_hex(c, &cl, &x);
|
|
|
|
|
assert(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
|
|
|
|
|
CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_wnaf(const secp256k1_num_t *number, int w) {
|
|
|
|
@ -394,19 +401,19 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
|
|
|
|
|
secp256k1_num_mul(&x, &x, &two);
|
|
|
|
|
int v = wnaf[i];
|
|
|
|
|
if (v) {
|
|
|
|
|
assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
|
|
|
|
|
CHECK(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
|
|
|
|
|
zeroes=0;
|
|
|
|
|
assert((v & 1) == 1); // check non-zero elements are odd
|
|
|
|
|
assert(v <= (1 << (w-1)) - 1); // check range below
|
|
|
|
|
assert(v >= -(1 << (w-1)) - 1); // check range above
|
|
|
|
|
CHECK((v & 1) == 1); // check non-zero elements are odd
|
|
|
|
|
CHECK(v <= (1 << (w-1)) - 1); // check range below
|
|
|
|
|
CHECK(v >= -(1 << (w-1)) - 1); // check range above
|
|
|
|
|
} else {
|
|
|
|
|
assert(zeroes != -1); // check that no unnecessary zero padding exists
|
|
|
|
|
CHECK(zeroes != -1); // check that no unnecessary zero padding exists
|
|
|
|
|
zeroes++;
|
|
|
|
|
}
|
|
|
|
|
secp256k1_num_set_int(&t, v);
|
|
|
|
|
secp256k1_num_add(&x, &x, &t);
|
|
|
|
|
}
|
|
|
|
|
assert(secp256k1_num_cmp(&x, number) == 0); // check that wnaf represents number
|
|
|
|
|
CHECK(secp256k1_num_cmp(&x, number) == 0); // check that wnaf represents number
|
|
|
|
|
secp256k1_num_free(&x);
|
|
|
|
|
secp256k1_num_free(&two);
|
|
|
|
|
secp256k1_num_free(&t);
|
|
|
|
@ -445,9 +452,9 @@ void test_ecdsa_sign_verify() {
|
|
|
|
|
secp256k1_ecdsa_sig_t sig;
|
|
|
|
|
secp256k1_ecdsa_sig_init(&sig);
|
|
|
|
|
random_sign(&sig, &key, &msg, NULL);
|
|
|
|
|
assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
|
|
|
|
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
|
|
|
|
secp256k1_num_inc(&msg);
|
|
|
|
|
assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
|
|
|
|
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
|
|
|
|
secp256k1_ecdsa_sig_free(&sig);
|
|
|
|
|
secp256k1_num_free(&msg);
|
|
|
|
|
secp256k1_num_free(&key);
|
|
|
|
@ -466,9 +473,9 @@ EC_KEY *get_openssl_key(const secp256k1_num_t *key) {
|
|
|
|
|
int compr = secp256k1_rand32() & 1;
|
|
|
|
|
const unsigned char* pbegin = privkey;
|
|
|
|
|
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
|
|
|
|
assert(secp256k1_ecdsa_privkey_serialize(privkey, &privkeylen, key, compr));
|
|
|
|
|
assert(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
|
|
|
|
|
assert(EC_KEY_check_key(ec_key));
|
|
|
|
|
CHECK(secp256k1_ecdsa_privkey_serialize(privkey, &privkeylen, key, compr));
|
|
|
|
|
CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
|
|
|
|
|
CHECK(EC_KEY_check_key(ec_key));
|
|
|
|
|
return ec_key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -486,21 +493,21 @@ void test_ecdsa_openssl() {
|
|
|
|
|
secp256k1_ge_t q;
|
|
|
|
|
secp256k1_ge_set_gej(&q, &qj);
|
|
|
|
|
EC_KEY *ec_key = get_openssl_key(&key);
|
|
|
|
|
assert(ec_key);
|
|
|
|
|
CHECK(ec_key);
|
|
|
|
|
unsigned char signature[80];
|
|
|
|
|
int sigsize = 80;
|
|
|
|
|
assert(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
|
|
|
|
|
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
|
|
|
|
|
secp256k1_ecdsa_sig_t sig;
|
|
|
|
|
secp256k1_ecdsa_sig_init(&sig);
|
|
|
|
|
assert(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
|
|
|
|
|
assert(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
|
|
|
|
|
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
|
|
|
|
|
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
|
|
|
|
|
secp256k1_num_inc(&sig.r);
|
|
|
|
|
assert(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
|
|
|
|
|
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
|
|
|
|
|
|
|
|
|
|
random_sign(&sig, &key, &msg, NULL);
|
|
|
|
|
sigsize = 80;
|
|
|
|
|
assert(secp256k1_ecdsa_sig_serialize(signature, &sigsize, &sig));
|
|
|
|
|
assert(ECDSA_verify(0, message, sizeof(message), signature, sigsize, ec_key) == 1);
|
|
|
|
|
CHECK(secp256k1_ecdsa_sig_serialize(signature, &sigsize, &sig));
|
|
|
|
|
CHECK(ECDSA_verify(0, message, sizeof(message), signature, sigsize, ec_key) == 1);
|
|
|
|
|
|
|
|
|
|
secp256k1_ecdsa_sig_free(&sig);
|
|
|
|
|
EC_KEY_free(ec_key);
|
|
|
|
|