From 86d3cce2a96b078323b032d21131c70d93258514 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 14 Jul 2013 17:43:13 +0200 Subject: [PATCH] Add support for multiplicative tweaking --- include/secp256k1.h | 6 +++-- src/secp256k1.c | 59 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index ac8169fb97..b74570d7ea 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -108,8 +108,10 @@ int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen); -int secp256k1_ecdsa_privkey_tweak(unsigned char *seckey, const unsigned char *tweak); -int secp256k1_ecdsa_pubkey_tweak(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); +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); #ifdef __cplusplus } diff --git a/src/secp256k1.c b/src/secp256k1.c index 1908780de5..c04b808993 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -146,7 +146,7 @@ int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { return 1; } -int secp256k1_ecdsa_privkey_tweak(unsigned char *seckey, const unsigned char *tweak) { +int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { int ret = 1; secp256k1_num_t term; secp256k1_num_init(&term); @@ -169,7 +169,7 @@ int secp256k1_ecdsa_privkey_tweak(unsigned char *seckey, const unsigned char *tw return ret; } -int secp256k1_ecdsa_pubkey_tweak(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { +int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { int ret = 1; secp256k1_num_t term; secp256k1_num_init(&term); @@ -185,6 +185,61 @@ int secp256k1_ecdsa_pubkey_tweak(unsigned char *pubkey, int pubkeylen, const uns secp256k1_gej_t pt; secp256k1_ecmult_gen(&pt, &term); secp256k1_gej_add_ge(&pt, &pt, &p); + if (secp256k1_gej_is_infinity(&pt)) + ret = 0; + secp256k1_ge_set_gej(&p, &pt); + int oldlen = pubkeylen; + secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); + assert(pubkeylen == oldlen); + } + secp256k1_num_free(&term); + return ret; +} + +int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { + int ret = 1; + secp256k1_num_t term; + secp256k1_num_init(&term); + secp256k1_num_set_bin(&term, tweak, 32); + if (secp256k1_num_is_zero(&term)) + ret = 0; + 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(&term, seckey, 32); + secp256k1_num_mod_mul(&sec, &sec, &term, &secp256k1_ge_consts->order); + } + if (ret) + secp256k1_num_get_bin(seckey, 32, &sec); + secp256k1_num_free(&sec); + secp256k1_num_free(&term); + return ret; +} + +int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { + int ret = 1; + secp256k1_num_t term; + secp256k1_num_init(&term); + secp256k1_num_set_bin(&term, tweak, 32); + if (secp256k1_num_is_zero(&term)) + ret = 0; + if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) + ret = 0; + secp256k1_ge_t p; + if (ret) { + if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) + ret = 0; + } + 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, &term, &zero); + secp256k1_num_free(&zero); secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);