From ae6bc76e32016063a591399a7a2d7bac646603bc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 27 Oct 2014 02:51:58 -0700 Subject: [PATCH 1/4] [API CHANGE] Use secp256k1_ec_ prefix for non-ECDSA key operations --- include/secp256k1.h | 47 ++++++++++++++++++++++++++++++++------------- src/secp256k1.c | 20 +++++++++---------- src/tests.c | 22 ++++++++++----------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index a8ddf43..cb5fd3c 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -87,13 +87,13 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, * 0: secret key is invalid * In: seckey: pointer to a 32-byte secret key */ -int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey); +int secp256k1_ec_seckey_verify(const unsigned char *seckey); /** Just validate a public key. * Returns: 1: valid public key * 0: invalid public key */ -int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); +int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen); /** Compute the public key for a secret key. * In: compressed: whether the computed public key should be compressed @@ -106,21 +106,42 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); * 0: secret was invalid, try again. * Requires starting using SECP256K1_START_SIGN. */ -int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); +int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); -int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); +/** Decompress a public key. + * In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key. + It must contain a 33-byte or 65-byte public key already. + * pubkeylen: pointer to the size of the public key pointed to be pubkey. + It will be updated to reflect the new size. + * Returns: 0 if the passed public key was invalid, 1 otherwise. If 1 is returned, the + pubkey is replaced with its decompressed version. + */ +int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); -int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, - unsigned char *privkey, int *privkeylen, - int compressed); +/** Export a private key in DER format. */ +int secp256k1_ec_privkey_export(const unsigned char *seckey, + unsigned char *privkey, int *privkeylen, + int compressed); -int secp256k1_ecdsa_privkey_import(unsigned char *seckey, - const unsigned char *privkey, int privkeylen); +/** Import a private key in DER format. */ +int secp256k1_ec_privkey_import(unsigned char *seckey, + const unsigned char *privkey, int privkeylen); -int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak); -int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); -int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak); -int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); +/** Tweak a private key by adding tweak to it. */ +int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak); + +/** Tweak a public key by adding tweak times the generator to it. + * Requires starting with SECP256K1_START_VERIFY. + */ +int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); + +/** Tweak a private key by multiplying it with tweak. */ +int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak); + +/** Tweak a public key by multiplying it with tweak. + * Requires starting with SECP256K1_START_VERIFY. + */ +int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); #ifdef __cplusplus } diff --git a/src/secp256k1.c b/src/secp256k1.c index b1ef48d..772ddff 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -165,7 +165,7 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const return ret; } -int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) { +int secp256k1_ec_seckey_verify(const unsigned char *seckey) { DEBUG_CHECK(seckey != NULL); secp256k1_num_t sec; @@ -178,14 +178,14 @@ int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) { return ret; } -int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { +int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { DEBUG_CHECK(pubkey != NULL); secp256k1_ge_t q; return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen); } -int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { +int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkeylen != NULL); @@ -204,7 +204,7 @@ int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const u return 1; } -int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { +int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkeylen != NULL); @@ -215,7 +215,7 @@ int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { return 1; } -int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { +int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(tweak != NULL); @@ -243,7 +243,7 @@ int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char return ret; } -int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { +int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { DEBUG_CHECK(secp256k1_ecmult_consts != NULL); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); @@ -278,7 +278,7 @@ int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const return ret; } -int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { +int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(tweak != NULL); @@ -303,7 +303,7 @@ int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char return ret; } -int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { +int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { DEBUG_CHECK(secp256k1_ecmult_consts != NULL); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); @@ -338,7 +338,7 @@ int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const return ret; } -int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { +int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(privkey != NULL); DEBUG_CHECK(privkeylen != NULL); @@ -351,7 +351,7 @@ int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *p return ret; } -int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { +int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(privkey != NULL); diff --git a/src/tests.c b/src/tests.c index 7f1d642..28bd4ee 100644 --- a/src/tests.c +++ b/src/tests.c @@ -560,28 +560,28 @@ void test_ecdsa_end_to_end() { } // Construct and verify corresponding public key. - CHECK(secp256k1_ecdsa_seckey_verify(privkey) == 1); + CHECK(secp256k1_ec_seckey_verify(privkey) == 1); char pubkey[65]; int pubkeylen = 65; - CHECK(secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1); - CHECK(secp256k1_ecdsa_pubkey_verify(pubkey, pubkeylen)); + 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_ecdsa_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); + CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); unsigned char privkey2[32]; - CHECK(secp256k1_ecdsa_privkey_import(privkey2, seckey, seckeylen) == 1); + 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_ecdsa_privkey_tweak_add(privkey, rnd); - int ret2 = secp256k1_ecdsa_pubkey_tweak_add(pubkey, pubkeylen, 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; char pubkey2[65]; int pubkeylen2 = 65; - CHECK(secp256k1_ecdsa_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); + CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } @@ -589,12 +589,12 @@ void test_ecdsa_end_to_end() { if (secp256k1_rand32() % 3 == 0) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); - int ret1 = secp256k1_ecdsa_privkey_tweak_mul(privkey, rnd); - int ret2 = secp256k1_ecdsa_pubkey_tweak_mul(pubkey, pubkeylen, 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; char pubkey2[65]; int pubkeylen2 = 65; - CHECK(secp256k1_ecdsa_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); + CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } From e2f71f1efe75ba20d710a57d701cebdcade67ddf Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 27 Oct 2014 02:57:27 -0700 Subject: [PATCH 2/4] Move non-ECDSA operations from ecdsa to eckey --- Makefile.am | 2 + src/ecdsa.h | 4 -- src/ecdsa_impl.h | 119 ----------------------------------------- src/eckey.h | 16 ++++++ src/eckey_impl.h | 134 +++++++++++++++++++++++++++++++++++++++++++++++ src/secp256k1.c | 1 + 6 files changed, 153 insertions(+), 123 deletions(-) create mode 100644 src/eckey.h create mode 100644 src/eckey_impl.h diff --git a/Makefile.am b/Makefile.am index adf778d..2cb6b8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,8 @@ noinst_HEADERS += src/num_gmp.h noinst_HEADERS += src/num_gmp_impl.h noinst_HEADERS += src/ecdsa.h noinst_HEADERS += src/ecdsa_impl.h +noinst_HEADERS += src/eckey.h +noinst_HEADERS += src/eckey_impl.h noinst_HEADERS += src/ecmult.h noinst_HEADERS += src/ecmult_impl.h noinst_HEADERS += src/ecmult_gen.h diff --git a/src/ecdsa.h b/src/ecdsa.h index d9faaa3..ff47f9b 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -14,15 +14,11 @@ typedef struct { void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r); void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r); -int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); -void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid); int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); -int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); -int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); #endif diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index 236108c..ee605ac 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -22,24 +22,6 @@ void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r) { secp256k1_num_free(&r->s); } -int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { - if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { - secp256k1_fe_t x; - secp256k1_fe_set_b32(&x, pub+1); - return secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); - } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { - secp256k1_fe_t x, y; - secp256k1_fe_set_b32(&x, pub+1); - secp256k1_fe_set_b32(&y, pub+33); - secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) - return 0; - return secp256k1_ge_is_valid(elem); - } else { - return 0; - } -} - int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { if (sig[0] != 0x30) return 0; int lenr = sig[3]; @@ -206,105 +188,4 @@ void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256 secp256k1_num_copy(&sig->s, s); } -void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { - secp256k1_fe_normalize(&elem->x); - secp256k1_fe_normalize(&elem->y); - secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { - *size = 33; - pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); - } else { - *size = 65; - pub[0] = 0x04; - secp256k1_fe_get_b32(&pub[33], &elem->y); - } -} - -int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { - const unsigned char *end = privkey + privkeylen; - // sequence header - if (end < privkey+1 || *privkey != 0x30) - return 0; - privkey++; - // sequence length constructor - int lenb = 0; - if (end < privkey+1 || !(*privkey & 0x80)) - return 0; - lenb = *privkey & ~0x80; privkey++; - if (lenb < 1 || lenb > 2) - return 0; - if (end < privkey+lenb) - return 0; - // sequence length - int len = 0; - len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); - privkey += lenb; - if (end < privkey+len) - return 0; - // sequence element 0: version number (=1) - if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) - return 0; - privkey += 3; - // sequence element 1: octet string, up to 32 bytes - if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) - return 0; - secp256k1_num_set_bin(key, privkey+2, privkey[1]); - return 1; -} - -int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { - secp256k1_gej_t rp; - secp256k1_ecmult_gen(&rp, key); - secp256k1_ge_t r; - secp256k1_ge_set_gej(&r, &rp); - if (compressed) { - static const unsigned char begin[] = { - 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - secp256k1_num_get_bin(ptr, 32, key); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - int pubkeylen = 0; - secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; - *privkeylen = ptr - privkey; - } else { - static const unsigned char begin[] = { - 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, - 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, - 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - secp256k1_num_get_bin(ptr, 32, key); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - int pubkeylen = 0; - secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; - *privkeylen = ptr - privkey; - } - return 1; -} - #endif diff --git a/src/eckey.h b/src/eckey.h new file mode 100644 index 0000000..81ae759 --- /dev/null +++ b/src/eckey.h @@ -0,0 +1,16 @@ +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _SECP256K1_ECKEY_ +#define _SECP256K1_ECKEY_ + +#include "group.h" +#include "num.h" + +int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); +void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); +int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); +int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); + +#endif diff --git a/src/eckey_impl.h b/src/eckey_impl.h new file mode 100644 index 0000000..acd521c --- /dev/null +++ b/src/eckey_impl.h @@ -0,0 +1,134 @@ +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _SECP256K1_ECKEY_IMPL_H_ +#define _SECP256K1_ECKEY_IMPL_H_ + +#include "eckey.h" + +#include "num.h" +#include "field.h" +#include "group.h" +#include "ecmult_gen.h" + +int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + secp256k1_fe_t x; + secp256k1_fe_set_b32(&x, pub+1); + return secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); + } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { + secp256k1_fe_t x, y; + secp256k1_fe_set_b32(&x, pub+1); + secp256k1_fe_set_b32(&y, pub+33); + secp256k1_ge_set_xy(elem, &x, &y); + if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) + return 0; + return secp256k1_ge_is_valid(elem); + } else { + return 0; + } +} + +void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { + secp256k1_fe_normalize(&elem->x); + secp256k1_fe_normalize(&elem->y); + secp256k1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + } else { + *size = 65; + pub[0] = 0x04; + secp256k1_fe_get_b32(&pub[33], &elem->y); + } +} + +int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { + const unsigned char *end = privkey + privkeylen; + // sequence header + if (end < privkey+1 || *privkey != 0x30) + return 0; + privkey++; + // sequence length constructor + int lenb = 0; + if (end < privkey+1 || !(*privkey & 0x80)) + return 0; + lenb = *privkey & ~0x80; privkey++; + if (lenb < 1 || lenb > 2) + return 0; + if (end < privkey+lenb) + return 0; + // sequence length + int len = 0; + len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + privkey += lenb; + if (end < privkey+len) + return 0; + // sequence element 0: version number (=1) + if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) + return 0; + privkey += 3; + // sequence element 1: octet string, up to 32 bytes + if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) + return 0; + secp256k1_num_set_bin(key, privkey+2, privkey[1]); + return 1; +} + +int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { + secp256k1_gej_t rp; + secp256k1_ecmult_gen(&rp, key); + secp256k1_ge_t r; + secp256k1_ge_set_gej(&r, &rp); + if (compressed) { + static const unsigned char begin[] = { + 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_num_get_bin(ptr, 32, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; + *privkeylen = ptr - privkey; + } else { + static const unsigned char begin[] = { + 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, + 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, + 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_num_get_bin(ptr, 32, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; + *privkeylen = ptr - privkey; + } + return 1; +} + +#endif diff --git a/src/secp256k1.c b/src/secp256k1.c index 772ddff..66c5647 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -12,6 +12,7 @@ #include "ecmult_impl.h" #include "ecmult_gen_impl.h" #include "ecdsa_impl.h" +#include "eckey_impl.h" void secp256k1_start(unsigned int flags) { secp256k1_fe_start(); From ffffc87855b74a68e9133fbb8fa616aaaca204f4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 27 Oct 2014 03:01:51 -0700 Subject: [PATCH 3/4] Use internal secp256k1_eckey_ prefix for functions in eckey --- src/eckey.h | 8 ++++---- src/eckey_impl.h | 12 ++++++------ src/secp256k1.c | 24 ++++++++++++------------ src/tests.c | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/eckey.h b/src/eckey.h index 81ae759..76e3da4 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -8,9 +8,9 @@ #include "group.h" #include "num.h" -int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); -void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); -int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); -int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); +int static secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); +void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); +int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); +int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); #endif diff --git a/src/eckey_impl.h b/src/eckey_impl.h index acd521c..9fa3fa4 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -12,7 +12,7 @@ #include "group.h" #include "ecmult_gen.h" -int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { +int static secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { secp256k1_fe_t x; secp256k1_fe_set_b32(&x, pub+1); @@ -30,7 +30,7 @@ int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned cha } } -void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { +void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { secp256k1_fe_normalize(&elem->x); secp256k1_fe_normalize(&elem->y); secp256k1_fe_get_b32(&pub[1], &elem->x); @@ -44,7 +44,7 @@ void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char } } -int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { +int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { const unsigned char *end = privkey + privkeylen; // sequence header if (end < privkey+1 || *privkey != 0x30) @@ -76,7 +76,7 @@ int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned ch return 1; } -int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { +int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { secp256k1_gej_t rp; secp256k1_ecmult_gen(&rp, key); secp256k1_ge_t r; @@ -101,7 +101,7 @@ int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privke secp256k1_num_get_bin(ptr, 32, key); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); int pubkeylen = 0; - secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; + secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; *privkeylen = ptr - privkey; } else { static const unsigned char begin[] = { @@ -125,7 +125,7 @@ int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privke secp256k1_num_get_bin(ptr, 32, key); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); int pubkeylen = 0; - secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; + secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; *privkeylen = ptr - privkey; } return 1; diff --git a/src/secp256k1.c b/src/secp256k1.c index 66c5647..8ad02a3 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -47,7 +47,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned secp256k1_ge_t q; secp256k1_num_set_bin(&m, msg, msglen); - if (!secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen)) { + if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) { ret = -1; goto end; } @@ -158,7 +158,7 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const secp256k1_ge_t q; if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { - secp256k1_ecdsa_pubkey_serialize(&q, pubkey, pubkeylen, compressed); + secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed); ret = 1; } secp256k1_ecdsa_sig_free(&sig); @@ -183,7 +183,7 @@ int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { DEBUG_CHECK(pubkey != NULL); secp256k1_ge_t q; - return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen); + return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen); } int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { @@ -201,7 +201,7 @@ int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsi secp256k1_num_free(&sec); secp256k1_ge_t p; secp256k1_ge_set_gej(&p, &pj); - secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); + secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed); return 1; } @@ -210,9 +210,9 @@ int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { DEBUG_CHECK(pubkeylen != NULL); secp256k1_ge_t p; - if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, *pubkeylen)) + if (!secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen)) return 0; - secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0); + secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0); return 1; } @@ -257,7 +257,7 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un ret = 0; secp256k1_ge_t p; if (ret) { - if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) + if (!secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen)) ret = 0; } if (ret) { @@ -272,7 +272,7 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un ret = 0; secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; - secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); + secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); VERIFY_CHECK(pubkeylen == oldlen); } secp256k1_num_free(&term); @@ -319,7 +319,7 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un ret = 0; secp256k1_ge_t p; if (ret) { - if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) + if (!secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen)) ret = 0; } if (ret) { @@ -332,7 +332,7 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un secp256k1_num_free(&zero); secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; - secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); + secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); VERIFY_CHECK(pubkeylen == oldlen); } secp256k1_num_free(&factor); @@ -347,7 +347,7 @@ int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *priv secp256k1_num_t key; secp256k1_num_init(&key); secp256k1_num_set_bin(&key, seckey, 32); - int ret = secp256k1_ecdsa_privkey_serialize(privkey, privkeylen, &key, compressed); + int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed); secp256k1_num_free(&key); return ret; } @@ -358,7 +358,7 @@ int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *priv secp256k1_num_t key; secp256k1_num_init(&key); - int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen); + int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); if (ret) secp256k1_num_get_bin(seckey, 32, &key); secp256k1_num_free(&key); diff --git a/src/tests.c b/src/tests.c index 28bd4ee..12a218f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -649,7 +649,7 @@ 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); - CHECK(secp256k1_ecdsa_privkey_serialize(privkey, &privkeylen, key, compr)); + CHECK(secp256k1_eckey_privkey_serialize(privkey, &privkeylen, key, compr)); CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); CHECK(EC_KEY_check_key(ec_key)); return ec_key; From eb74c36bd29234fdc33ff1d052a39aeaa710c5b2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 27 Oct 2014 03:27:55 -0700 Subject: [PATCH 4/4] Abstract out tweak logic to secp256k1_eckey_* functions --- src/eckey.h | 6 +++++ src/eckey_impl.h | 55 ++++++++++++++++++++++++++++++++++++++++ src/secp256k1.c | 66 +++++++++++++----------------------------------- 3 files changed, 78 insertions(+), 49 deletions(-) diff --git a/src/eckey.h b/src/eckey.h index 76e3da4..2396d97 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -10,7 +10,13 @@ int static secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); + int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); +int static secp256k1_eckey_privkey_tweak_add(secp256k1_num_t *key, const secp256k1_num_t *tweak); +int static secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak); +int static secp256k1_eckey_privkey_tweak_mul(secp256k1_num_t *key, const secp256k1_num_t *tweak); +int static secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak); + #endif diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 9fa3fa4..70d7616 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -131,4 +131,59 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke return 1; } +int static secp256k1_eckey_privkey_tweak_add(secp256k1_num_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + secp256k1_num_add(key, key, tweak); + secp256k1_num_mod(key, &secp256k1_ge_consts->order); + if (secp256k1_num_is_zero(key)) + return 0; + return 1; +} + +int static secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + + secp256k1_gej_t pt; + secp256k1_gej_set_ge(&pt, key); + secp256k1_num_t one; + secp256k1_num_init(&one); + secp256k1_num_set_int(&one, 1); + secp256k1_ecmult(&pt, &pt, &one, tweak); + secp256k1_num_free(&one); + + if (secp256k1_gej_is_infinity(&pt)) + return 0; + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +int static secp256k1_eckey_privkey_tweak_mul(secp256k1_num_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_is_zero(tweak)) + return 0; + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + + secp256k1_num_mod_mul(key, key, tweak, &secp256k1_ge_consts->order); + return 1; +} + +int static secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_is_zero(tweak)) + return 0; + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + + secp256k1_num_t zero; + secp256k1_num_init(&zero); + secp256k1_num_set_int(&zero, 0); + secp256k1_gej_t pt; + secp256k1_gej_set_ge(&pt, key); + secp256k1_ecmult(&pt, &pt, tweak, &zero); + secp256k1_num_free(&zero); + secp256k1_ge_set_gej(key, &pt); + return 1; +} + #endif diff --git a/src/secp256k1.c b/src/secp256k1.c index 8ad02a3..94026dd 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -220,23 +220,18 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t 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); + secp256k1_num_set_bin(&sec, seckey, 32); + + int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term); 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); @@ -249,32 +244,20 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un DEBUG_CHECK(pubkey != 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_ge_t p; + int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); if (ret) { - if (!secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen)) - ret = 0; + ret = secp256k1_eckey_pubkey_tweak_add(&p, &term); } if (ret) { - secp256k1_gej_t pt; - secp256k1_gej_set_ge(&pt, &p); - secp256k1_num_t one; - secp256k1_num_init(&one); - secp256k1_num_set_int(&one, 1); - secp256k1_ecmult(&pt, &pt, &one, &term); - secp256k1_num_free(&one); - if (secp256k1_gej_is_infinity(&pt)) - ret = 0; - secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); VERIFY_CHECK(pubkeylen == oldlen); } + secp256k1_num_free(&term); return ret; } @@ -283,22 +266,19 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(tweak != NULL); - 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); + secp256k1_num_set_bin(&sec, seckey, 32); + int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor); 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_clear(&sec); + secp256k1_num_clear(&factor); secp256k1_num_free(&sec); secp256k1_num_free(&factor); return ret; @@ -309,32 +289,20 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); - 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_ge_t p; + int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); if (ret) { - if (!secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen)) - ret = 0; + ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor); } if (ret) { - secp256k1_num_t zero; - secp256k1_num_init(&zero); - secp256k1_num_set_int(&zero, 0); - secp256k1_gej_t pt; - secp256k1_gej_set_ge(&pt, &p); - secp256k1_ecmult(&pt, &pt, &factor, &zero); - secp256k1_num_free(&zero); - secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); VERIFY_CHECK(pubkeylen == oldlen); } + secp256k1_num_free(&factor); return ret; }