int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { secp256k1_num_t sec, non, msg; secp256k1_num_init(&sec); secp256k1_num_init(&non); secp256k1_num_init(&msg); secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_num_set_bin(&non, nonce, 32); secp256k1_num_set_bin(&msg, message, messagelen); int ret = !secp256k1_num_is_zero(&non) && (secp256k1_num_cmp(&non, &secp256k1_ge_consts->order) < 0); secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_init(&sig); if (ret) { ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); } if (ret) { secp256k1_num_get_bin(sig64, 32, &sig.r); secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); } secp256k1_ecdsa_sig_free(&sig); secp256k1_num_clear(&msg); secp256k1_num_clear(&non); secp256k1_num_clear(&sec); secp256k1_num_free(&msg); secp256k1_num_free(&non); secp256k1_num_free(&sec); return ret; }
int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(tweak != NULL); int ret = 1; secp256k1_num_t term; secp256k1_num_init(&term); secp256k1_num_set_bin(&term, tweak, 32); if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) ret = 0; secp256k1_num_t sec; secp256k1_num_init(&sec); if (ret) { secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_num_add(&sec, &sec, &term); secp256k1_num_mod(&sec, &secp256k1_ge_consts->order); if (secp256k1_num_is_zero(&sec)) ret = 0; } if (ret) secp256k1_num_get_bin(seckey, 32, &sec); secp256k1_num_clear(&sec); secp256k1_num_clear(&term); secp256k1_num_free(&sec); secp256k1_num_free(&term); return ret; }
void run_scalar_tests(void) { for (int i = 0; i < 128 * count; i++) { scalar_test(); } { /* (-1)+1 should be zero. */ secp256k1_scalar_t s, o; secp256k1_scalar_set_int(&s, 1); secp256k1_scalar_negate(&o, &s); secp256k1_scalar_add(&o, &o, &s); CHECK(secp256k1_scalar_is_zero(&o)); } #ifndef USE_NUM_NONE { /* A scalar with value of the curve order should be 0. */ secp256k1_num_t order; secp256k1_scalar_order_get_num(&order); unsigned char bin[32]; secp256k1_num_get_bin(bin, 32, &order); secp256k1_scalar_t zero; int overflow = 0; secp256k1_scalar_set_b32(&zero, bin, &overflow); CHECK(overflow == 1); CHECK(secp256k1_scalar_is_zero(&zero)); } #endif }
int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { secp256k1_num_t key; secp256k1_num_init(&key); int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen); if (ret) secp256k1_num_get_bin(seckey, 32, &key); secp256k1_num_free(&key); return ret; }
void run_num_int(void) { secp256k1_num_t n1; for (int i=-255; i<256; i++) { unsigned char c1[3] = {}; c1[2] = abs(i); unsigned char c2[3] = {0x11,0x22,0x33}; secp256k1_num_set_int(&n1, i); secp256k1_num_get_bin(c2, 3, &n1); CHECK(memcmp(c1, c2, 3) == 0); } }
void test_num_get_set_bin(void) { secp256k1_num_t n1,n2; random_num_order_test(&n1); unsigned char c[32]; secp256k1_num_get_bin(c, 32, &n1); secp256k1_num_set_bin(&n2, c, 32); CHECK(secp256k1_num_eq(&n1, &n2)); 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]; 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); CHECK(secp256k1_num_eq(&n1, &n2)); } }
int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { int ret = 1; secp256k1_num_t factor; secp256k1_num_init(&factor); secp256k1_num_set_bin(&factor, tweak, 32); if (secp256k1_num_is_zero(&factor)) ret = 0; if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) ret = 0; secp256k1_num_t sec; secp256k1_num_init(&sec); if (ret) { secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_num_mod_mul(&sec, &sec, &factor, &secp256k1_ge_consts->order); } if (ret) secp256k1_num_get_bin(seckey, 32, &sec); secp256k1_num_free(&sec); secp256k1_num_free(&factor); return ret; }
void test_num_get_set_bin() { secp256k1_num_t n1,n2; secp256k1_num_init(&n1); secp256k1_num_init(&n2); random_num_order_test(&n1); 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); 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); // 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); } secp256k1_num_free(&n2); secp256k1_num_free(&n1); }
void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; /* Generate a random key and message. */ { secp256k1_num_t msg, key; random_num_order_test(&msg); random_num_order_test(&key); secp256k1_num_get_bin(privkey, 32, &key); secp256k1_num_get_bin(message, 32, &msg); } /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(privkey) == 1); unsigned char pubkey[65]; int pubkeylen = 65; CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1); CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen)); /* Verify private key import and export. */ unsigned char seckey[300]; int seckeylen = 300; CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); unsigned char privkey2[32]; CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1); CHECK(memcmp(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ if (secp256k1_rand32() % 3 == 0) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); int ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd); int ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd); CHECK(ret1 == ret2); if (ret1 == 0) return; unsigned char pubkey2[65]; int pubkeylen2 = 65; CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } /* Optionally tweak the keys using multiplication. */ if (secp256k1_rand32() % 3 == 0) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); int ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd); int ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd); CHECK(ret1 == ret2); if (ret1 == 0) return; unsigned char pubkey2[65]; int pubkeylen2 = 65; CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } /* Sign. */ unsigned char signature[72]; int signaturelen = 72; while(1) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); if (secp256k1_ecdsa_sign(message, 32, signature, &signaturelen, privkey, rnd) == 1) { break; } } /* Verify. */ CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) == 1); /* Destroy signature and verify again. */ signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) != 1); /* Compact sign. */ unsigned char csignature[64]; int recid = 0; while(1) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); if (secp256k1_ecdsa_sign_compact(message, 32, csignature, privkey, rnd, &recid) == 1) { break; } } /* Recover. */ unsigned char recpubkey[65]; int recpubkeylen = 0; CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); CHECK(recpubkeylen == pubkeylen); CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0); /* Destroy signature and verify again. */ csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 || memcmp(pubkey, recpubkey, pubkeylen) != 0); CHECK(recpubkeylen == pubkeylen); }
void scalar_test(void) { unsigned char c[32]; /* Set 's' to a random scalar, with value 'snum'. */ secp256k1_rand256_test(c); secp256k1_scalar_t s; secp256k1_scalar_set_b32(&s, c, NULL); secp256k1_num_t snum; secp256k1_num_set_bin(&snum, c, 32); secp256k1_num_mod(&snum, &secp256k1_ge_consts->order); /* Set 's1' to a random scalar, with value 's1num'. */ secp256k1_rand256_test(c); secp256k1_scalar_t s1; secp256k1_scalar_set_b32(&s1, c, NULL); secp256k1_num_t s1num; secp256k1_num_set_bin(&s1num, c, 32); secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order); /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ secp256k1_rand256_test(c); secp256k1_scalar_t s2; int overflow = 0; secp256k1_scalar_set_b32(&s2, c, &overflow); secp256k1_num_t s2num; secp256k1_num_set_bin(&s2num, c, 32); secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order); { /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ secp256k1_num_t n, t, m; secp256k1_num_set_int(&n, 0); secp256k1_num_set_int(&m, 16); for (int i = 0; i < 256; i += 4) { secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); secp256k1_num_mul(&n, &n, &m); secp256k1_num_add(&n, &n, &t); } CHECK(secp256k1_num_eq(&n, &snum)); } { /* Test that get_b32 returns the same as get_bin on the number. */ unsigned char r1[32]; secp256k1_scalar_get_b32(r1, &s2); unsigned char r2[32]; secp256k1_num_get_bin(r2, 32, &s2num); CHECK(memcmp(r1, r2, 32) == 0); /* If no overflow occurred when assigning, it should also be equal to the original byte array. */ CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0)); } { /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ secp256k1_num_t rnum; secp256k1_num_add(&rnum, &snum, &s2num); secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); secp256k1_scalar_t r; secp256k1_scalar_add(&r, &s, &s2); secp256k1_num_t r2num; secp256k1_scalar_get_num(&r2num, &r); CHECK(secp256k1_num_eq(&rnum, &r2num)); } { /* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */ secp256k1_num_t rnum; secp256k1_num_mul(&rnum, &snum, &s2num); secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); secp256k1_scalar_t r; secp256k1_scalar_mul(&r, &s, &s2); secp256k1_num_t r2num; secp256k1_scalar_get_num(&r2num, &r); CHECK(secp256k1_num_eq(&rnum, &r2num)); /* The result can only be zero if at least one of the factors was zero. */ CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); } { /* Check that comparison with zero matches comparison with zero on the number. */ CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); /* Check that comparison with the half order is equal to testing for high scalar. */ CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0)); secp256k1_scalar_t neg; secp256k1_scalar_negate(&neg, &s); secp256k1_num_t negnum; secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum); secp256k1_num_mod(&negnum, &secp256k1_ge_consts->order); /* Check that comparison with the half order is equal to testing for high scalar after negation. */ CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &secp256k1_ge_consts->half_order) > 0)); /* Negating should change the high property, unless the value was already zero. */ CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); secp256k1_num_t negnum2; secp256k1_scalar_get_num(&negnum2, &neg); /* Negating a scalar should be equal to (order - n) mod order on the number. */ CHECK(secp256k1_num_eq(&negnum, &negnum2)); secp256k1_scalar_add(&neg, &neg, &s); /* Adding a number to its negation should result in zero. */ CHECK(secp256k1_scalar_is_zero(&neg)); secp256k1_scalar_negate(&neg, &neg); /* Negating zero should still result in zero. */ CHECK(secp256k1_scalar_is_zero(&neg)); } { /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ if (!secp256k1_scalar_is_zero(&s)) { secp256k1_scalar_t inv; secp256k1_scalar_inverse(&inv, &s); secp256k1_num_t invnum; secp256k1_num_mod_inverse(&invnum, &snum, &secp256k1_ge_consts->order); secp256k1_num_t invnum2; secp256k1_scalar_get_num(&invnum2, &inv); CHECK(secp256k1_num_eq(&invnum, &invnum2)); secp256k1_scalar_mul(&inv, &inv, &s); /* Multiplying a scalar with its inverse must result in one. */ CHECK(secp256k1_scalar_is_one(&inv)); secp256k1_scalar_inverse(&inv, &inv); /* Inverting one must result in one. */ CHECK(secp256k1_scalar_is_one(&inv)); } } { /* Test commutativity of add. */ secp256k1_scalar_t r1, r2; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_add(&r2, &s2, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test commutativity of mul. */ secp256k1_scalar_t r1, r2; secp256k1_scalar_mul(&r1, &s1, &s2); secp256k1_scalar_mul(&r2, &s2, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test associativity of add. */ secp256k1_scalar_t r1, r2; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_add(&r1, &r1, &s); secp256k1_scalar_add(&r2, &s2, &s); secp256k1_scalar_add(&r2, &s1, &r2); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test associativity of mul. */ secp256k1_scalar_t r1, r2; secp256k1_scalar_mul(&r1, &s1, &s2); secp256k1_scalar_mul(&r1, &r1, &s); secp256k1_scalar_mul(&r2, &s2, &s); secp256k1_scalar_mul(&r2, &s1, &r2); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test distributitivity of mul over add. */ secp256k1_scalar_t r1, r2, t; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_mul(&r1, &r1, &s); secp256k1_scalar_mul(&r2, &s1, &s); secp256k1_scalar_mul(&t, &s2, &s); secp256k1_scalar_add(&r2, &r2, &t); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test square. */ secp256k1_scalar_t r1, r2; secp256k1_scalar_sqr(&r1, &s1); secp256k1_scalar_mul(&r2, &s1, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } }