Merge #558: Add schnorrsig module which implements BIP-340 compliant signatures
f431b3f28avalgrind_ctime_test: Add schnorrsig_sign (Jonas Nick)16ffa9d97cschnorrsig: Add taproot test case (Jonas Nick)8dfd53ee3fschnorrsig: Add benchmark for sign and verify (Jonas Nick)4e43520026schnorrsig: Add BIP-340 compatible signing and verification (Jonas Nick)7332d2db6bschnorrsig: Add BIP-340 nonce function (Jonas Nick)7a703fd97dschnorrsig: Init empty experimental module (Jonas Nick)eabd9bc46aAllow initializing tagged sha256 (Jonas Nick)6fcb5b845dextrakeys: Add keypair_xonly_tweak_add (Jonas Nick)58254463f9extrakeys: Add keypair struct with create, pub and pub_xonly (Jonas Nick)f0010349b8Separate helper functions for pubkey_create and seckey_tweak_add (Jonas Nick)910d9c284cextrakeys: Add xonly_pubkey_tweak_add & xonly_pubkey_tweak_add_test (Jonas Nick)176bfb1110Separate helper function for ec_pubkey_tweak_add (Jonas Nick)4cd2ee474dextrakeys: Add xonly_pubkey with serialize, parse and from_pubkey (Jonas Nick)47e6618e11extrakeys: Init empty experimental module (Jonas Nick)3e08b02e2aMake the secp256k1_declassify argument constant (Jonas Nick) Pull request description: This PR implements signing, verification and batch verification as described in [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) in an experimental module named `schnorrsig`. It includes the test vectors and a benchmarking tool. This PR also adds a module `extrakeys` that allows [BIP-341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)-style key tweaking. (Adding ChaCha20 as a CSPRNG and batch verification was moved to PR #760). In order to enable the module run `./configure` with `--enable-experimental --enable-module-schnorrsig`. Based on apoelstra's work. ACKs for top commit: gmaxwell: ACKf431b3f28a(exactly matches the previous post-fixup version which I have already reviewed and tested) sipa: ACKf431b3f28areal-or-random: ACKf431b3f28acareful code review Tree-SHA512: e15e849c7bb65cdc5d7b1d6874678e275a71e4514de9d5432ec1700de3ba92aa9f381915813f4729057af152d90eea26aabb976ed297019c5767e59cf0bbc693
This commit is contained in:
@@ -231,7 +231,7 @@ void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scr
|
||||
* of the software. This is setup for use with valgrind but could be substituted with
|
||||
* the appropriate instrumentation for other analysis tools.
|
||||
*/
|
||||
static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, void *p, size_t len) {
|
||||
static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) {
|
||||
#if defined(VALGRIND)
|
||||
if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len);
|
||||
#else
|
||||
@@ -553,10 +553,21 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) {
|
||||
static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey) {
|
||||
secp256k1_gej pj;
|
||||
int ret;
|
||||
|
||||
ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey);
|
||||
secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret);
|
||||
|
||||
secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar);
|
||||
secp256k1_ge_set_gej(p, &pj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) {
|
||||
secp256k1_ge p;
|
||||
secp256k1_scalar sec;
|
||||
secp256k1_scalar seckey_scalar;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
@@ -564,15 +575,11 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(seckey != NULL);
|
||||
|
||||
ret = secp256k1_scalar_set_b32_seckey(&sec, seckey);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !ret);
|
||||
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
memczero(pubkey, sizeof(*pubkey), !ret);
|
||||
|
||||
secp256k1_scalar_clear(&sec);
|
||||
secp256k1_scalar_clear(&seckey_scalar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -610,24 +617,31 @@ int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *p
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
||||
|
||||
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak) {
|
||||
secp256k1_scalar term;
|
||||
int overflow = 0;
|
||||
int ret = 0;
|
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(sec, &term);
|
||||
secp256k1_scalar_clear(&term);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
||||
secp256k1_scalar sec;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(seckey != NULL);
|
||||
ARG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
ret = secp256k1_scalar_set_b32_seckey(&sec, seckey);
|
||||
|
||||
ret &= (!overflow) & secp256k1_eckey_privkey_tweak_add(&sec, &term);
|
||||
ret &= secp256k1_ec_seckey_tweak_add_helper(&sec, tweak);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret);
|
||||
secp256k1_scalar_get_b32(seckey, &sec);
|
||||
|
||||
secp256k1_scalar_clear(&sec);
|
||||
secp256k1_scalar_clear(&term);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -635,25 +649,26 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
|
||||
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak);
|
||||
}
|
||||
|
||||
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak) {
|
||||
secp256k1_scalar term;
|
||||
int overflow = 0;
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term);
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) {
|
||||
secp256k1_ge p;
|
||||
secp256k1_scalar term;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
ARG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak);
|
||||
if (ret) {
|
||||
if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) {
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -746,3 +761,11 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
# include "modules/recovery/main_impl.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_EXTRAKEYS
|
||||
# include "modules/extrakeys/main_impl.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORRSIG
|
||||
# include "modules/schnorrsig/main_impl.h"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user