mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-18 22:35:39 +01:00
0cdc758a563 Merge bitcoin-core/secp256k1#1631: release: prepare for 0.6.0 39d5dfd542a release: prepare for 0.6.0 df2eceb2790 build: add ellswift.md and musig.md to release tarball a306bb7e903 tools: fix check-abi.sh after cmake out locations were changed 145868a84d2 Do not export `secp256k1_musig_nonce_gen_internal` b161bffb8bf Merge bitcoin-core/secp256k1#1579: Clear sensitive memory without getting optimized out (revival of #636) a38d879a1a6 Merge bitcoin-core/secp256k1#1628: Name public API structs 7d48f5ed02e Merge bitcoin-core/secp256k1#1581: test, ci: Lower default iteration count to 16 694342fdb71 Name public API structs 0f73caf7c62 test, ci: Lower default iteration count to 16 9a8db52f4e9 Merge bitcoin-core/secp256k1#1582: cmake, test: Add `secp256k1_` prefix to test names 765ef53335a Clear _gej instances after point multiplication to avoid potential leaks 349e6ab916b Introduce separate _clear functions for hash module 99cc9fd6d01 Don't rely on memset to set signed integers to 0 97c57f42ba8 Implement various _clear() functions with secp256k1_memclear() 9bb368d1466 Use secp256k1_memclear() to clear stack memory instead of memset() e3497bbf001 Separate between clearing memory and setting to zero in tests d79a6ccd43a Separate secp256k1_fe_set_int( . , 0 ) from secp256k1_fe_clear() 1c081262227 Add secp256k1_memclear() for clearing secret data 1464f15c812 Merge bitcoin-core/secp256k1#1625: util: Remove unused (u)int64_t formatting macros 980c08df80a util: Remove unused (u)int64_t formatting macros 9b7c59cbb90 Merge bitcoin-core/secp256k1#1624: ci: Update macOS image 096e3e23f63 ci: Update macOS image e7d384488e8 Don't clear secrets in pippenger implementation 68b55209f1b Merge bitcoin-core/secp256k1#1619: musig: ctimetests: fix _declassify range for generated nonce points f0868a9b3d8 Merge bitcoin-core/secp256k1#1595: build: 45839th attempt to fix symbol visibility on Windows 1fae76f50c0 Merge bitcoin-core/secp256k1#1620: Remove unused scratch space from API 8be3839fb2e Remove unused scratch space from API 57eda3ba300 musig: ctimetests: fix _declassify range for generated nonce points 87384f5c0f2 cmake, test: Add `secp256k1_` prefix to test names e59158b6eb7 Merge bitcoin-core/secp256k1#1553: cmake: Set top-level target output locations 18f9b967c25 Merge bitcoin-core/secp256k1#1616: examples: do not retry generating seckey randomness in musig 5bab8f6d3c4 examples: make key generation doc consistent e8908221a45 examples: do not retry generating seckey randomness in musig 70b6be1834e extrakeys: improve doc of keypair_create (don't suggest retry) 01b5893389e Merge bitcoin-core/secp256k1#1599: #1570 improve examples: remove key generation loop cd4f84f3ba8 Improve examples/documentation: remove key generation loops a88aa935063 Merge bitcoin-core/secp256k1#1603: f can never equal -m 3660fe5e2a9 Merge bitcoin-core/secp256k1#1479: Add module "musig" that implements MuSig2 multi-signatures (BIP 327) 168c92011f5 build: allow enabling the musig module in cmake f411841a46b Add module "musig" that implements MuSig2 multi-signatures (BIP 327) 0be79660f38 util: add constant-time is_zero_array function c8fbdb1b972 group: add ge_to_bytes_ext and ge_from_bytes_ext ef7ff03407f f can never equal -m c232486d84e Revert "cmake: Set `ENVIRONMENT` property for examples on Windows" 26e4a7c2146 cmake: Set top-level target output locations 4c57c7a5a95 Merge bitcoin-core/secp256k1#1554: cmake: Clean up testing code 447334cb06d include: Avoid visibility("default") on Windows 472faaa8ee6 Merge bitcoin-core/secp256k1#1604: doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description 292310fbb24 doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description 85e224dd97f group: add ge_to_bytes and ge_from_bytes 7c987ec89e6 cmake: Call `enable_testing()` unconditionally 6aa576515ef cmake: Delete `CTest` module git-subtree-dir: src/secp256k1 git-subtree-split: 0cdc758a56360bf58a851fe91085a327ec97685a
270 lines
9.9 KiB
C
270 lines
9.9 KiB
C
/***********************************************************************
|
|
* Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick *
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
|
***********************************************************************/
|
|
|
|
#ifndef SECP256K1_MODULE_SCHNORRSIG_MAIN_H
|
|
#define SECP256K1_MODULE_SCHNORRSIG_MAIN_H
|
|
|
|
#include "../../../include/secp256k1.h"
|
|
#include "../../../include/secp256k1_schnorrsig.h"
|
|
#include "../../hash.h"
|
|
|
|
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
|
|
* SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */
|
|
static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) {
|
|
secp256k1_sha256_initialize(sha);
|
|
sha->s[0] = 0x46615b35ul;
|
|
sha->s[1] = 0xf4bfbff7ul;
|
|
sha->s[2] = 0x9f8dc671ul;
|
|
sha->s[3] = 0x83627ab3ul;
|
|
sha->s[4] = 0x60217180ul;
|
|
sha->s[5] = 0x57358661ul;
|
|
sha->s[6] = 0x21a29e54ul;
|
|
sha->s[7] = 0x68b07b4cul;
|
|
|
|
sha->bytes = 64;
|
|
}
|
|
|
|
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
|
|
* SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */
|
|
static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) {
|
|
secp256k1_sha256_initialize(sha);
|
|
sha->s[0] = 0x24dd3219ul;
|
|
sha->s[1] = 0x4eba7e70ul;
|
|
sha->s[2] = 0xca0fabb9ul;
|
|
sha->s[3] = 0x0fa3166dul;
|
|
sha->s[4] = 0x3afbe4b1ul;
|
|
sha->s[5] = 0x4c44df97ul;
|
|
sha->s[6] = 0x4aac2739ul;
|
|
sha->s[7] = 0x249e850aul;
|
|
|
|
sha->bytes = 64;
|
|
}
|
|
|
|
/* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
|
|
* by using the correct tagged hash function. */
|
|
static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'};
|
|
|
|
static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC;
|
|
|
|
static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
|
|
secp256k1_sha256 sha;
|
|
unsigned char masked_key[32];
|
|
int i;
|
|
|
|
if (algo == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (data != NULL) {
|
|
secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha);
|
|
secp256k1_sha256_write(&sha, data, 32);
|
|
secp256k1_sha256_finalize(&sha, masked_key);
|
|
for (i = 0; i < 32; i++) {
|
|
masked_key[i] ^= key32[i];
|
|
}
|
|
} else {
|
|
/* Precomputed TaggedHash("BIP0340/aux", 0x0000...00); */
|
|
static const unsigned char ZERO_MASK[32] = {
|
|
84, 241, 105, 207, 201, 226, 229, 114,
|
|
116, 128, 68, 31, 144, 186, 37, 196,
|
|
136, 244, 97, 199, 11, 94, 165, 220,
|
|
170, 247, 175, 105, 39, 10, 165, 20
|
|
};
|
|
for (i = 0; i < 32; i++) {
|
|
masked_key[i] = key32[i] ^ ZERO_MASK[i];
|
|
}
|
|
}
|
|
|
|
/* Tag the hash with algo which is important to avoid nonce reuse across
|
|
* algorithms. If this nonce function is used in BIP-340 signing as defined
|
|
* in the spec, an optimized tagging implementation is used. */
|
|
if (algolen == sizeof(bip340_algo)
|
|
&& secp256k1_memcmp_var(algo, bip340_algo, algolen) == 0) {
|
|
secp256k1_nonce_function_bip340_sha256_tagged(&sha);
|
|
} else {
|
|
secp256k1_sha256_initialize_tagged(&sha, algo, algolen);
|
|
}
|
|
|
|
/* Hash masked-key||pk||msg using the tagged hash as per the spec */
|
|
secp256k1_sha256_write(&sha, masked_key, 32);
|
|
secp256k1_sha256_write(&sha, xonly_pk32, 32);
|
|
secp256k1_sha256_write(&sha, msg, msglen);
|
|
secp256k1_sha256_finalize(&sha, nonce32);
|
|
secp256k1_sha256_clear(&sha);
|
|
return 1;
|
|
}
|
|
|
|
const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340;
|
|
|
|
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
|
|
* SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */
|
|
static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) {
|
|
secp256k1_sha256_initialize(sha);
|
|
sha->s[0] = 0x9cecba11ul;
|
|
sha->s[1] = 0x23925381ul;
|
|
sha->s[2] = 0x11679112ul;
|
|
sha->s[3] = 0xd1627e0ful;
|
|
sha->s[4] = 0x97c87550ul;
|
|
sha->s[5] = 0x003cc765ul;
|
|
sha->s[6] = 0x90f61164ul;
|
|
sha->s[7] = 0x33e9b66aul;
|
|
sha->bytes = 64;
|
|
}
|
|
|
|
static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32)
|
|
{
|
|
unsigned char buf[32];
|
|
secp256k1_sha256 sha;
|
|
|
|
/* tagged hash(r.x, pk.x, msg) */
|
|
secp256k1_schnorrsig_sha256_tagged(&sha);
|
|
secp256k1_sha256_write(&sha, r32, 32);
|
|
secp256k1_sha256_write(&sha, pubkey32, 32);
|
|
secp256k1_sha256_write(&sha, msg, msglen);
|
|
secp256k1_sha256_finalize(&sha, buf);
|
|
/* Set scalar e to the challenge hash modulo the curve order as per
|
|
* BIP340. */
|
|
secp256k1_scalar_set_b32(e, buf, NULL);
|
|
}
|
|
|
|
static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
|
|
secp256k1_scalar sk;
|
|
secp256k1_scalar e;
|
|
secp256k1_scalar k;
|
|
secp256k1_gej rj;
|
|
secp256k1_ge pk;
|
|
secp256k1_ge r;
|
|
unsigned char buf[32] = { 0 };
|
|
unsigned char pk_buf[32];
|
|
unsigned char seckey[32];
|
|
int ret = 1;
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
|
ARG_CHECK(sig64 != NULL);
|
|
ARG_CHECK(msg != NULL || msglen == 0);
|
|
ARG_CHECK(keypair != NULL);
|
|
|
|
if (noncefp == NULL) {
|
|
noncefp = secp256k1_nonce_function_bip340;
|
|
}
|
|
|
|
ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair);
|
|
/* Because we are signing for a x-only pubkey, the secret key is negated
|
|
* before signing if the point corresponding to the secret key does not
|
|
* have an even Y. */
|
|
if (secp256k1_fe_is_odd(&pk.y)) {
|
|
secp256k1_scalar_negate(&sk, &sk);
|
|
}
|
|
|
|
secp256k1_scalar_get_b32(seckey, &sk);
|
|
secp256k1_fe_get_b32(pk_buf, &pk.x);
|
|
ret &= !!noncefp(buf, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
|
|
secp256k1_scalar_set_b32(&k, buf, NULL);
|
|
ret &= !secp256k1_scalar_is_zero(&k);
|
|
secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
|
|
|
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k);
|
|
secp256k1_ge_set_gej(&r, &rj);
|
|
|
|
/* We declassify r to allow using it as a branch point. This is fine
|
|
* because r is not a secret. */
|
|
secp256k1_declassify(ctx, &r, sizeof(r));
|
|
secp256k1_fe_normalize_var(&r.y);
|
|
if (secp256k1_fe_is_odd(&r.y)) {
|
|
secp256k1_scalar_negate(&k, &k);
|
|
}
|
|
secp256k1_fe_normalize_var(&r.x);
|
|
secp256k1_fe_get_b32(&sig64[0], &r.x);
|
|
|
|
secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf);
|
|
secp256k1_scalar_mul(&e, &e, &sk);
|
|
secp256k1_scalar_add(&e, &e, &k);
|
|
secp256k1_scalar_get_b32(&sig64[32], &e);
|
|
|
|
secp256k1_memczero(sig64, 64, !ret);
|
|
secp256k1_scalar_clear(&k);
|
|
secp256k1_scalar_clear(&sk);
|
|
secp256k1_memclear(seckey, sizeof(seckey));
|
|
secp256k1_gej_clear(&rj);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int secp256k1_schnorrsig_sign32(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
|
|
/* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */
|
|
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, (unsigned char*)aux_rand32);
|
|
}
|
|
|
|
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
|
|
return secp256k1_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32);
|
|
}
|
|
|
|
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) {
|
|
secp256k1_nonce_function_hardened noncefp = NULL;
|
|
void *ndata = NULL;
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
if (extraparams != NULL) {
|
|
ARG_CHECK(secp256k1_memcmp_var(extraparams->magic,
|
|
schnorrsig_extraparams_magic,
|
|
sizeof(extraparams->magic)) == 0);
|
|
noncefp = extraparams->noncefp;
|
|
ndata = extraparams->ndata;
|
|
}
|
|
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata);
|
|
}
|
|
|
|
int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey) {
|
|
secp256k1_scalar s;
|
|
secp256k1_scalar e;
|
|
secp256k1_gej rj;
|
|
secp256k1_ge pk;
|
|
secp256k1_gej pkj;
|
|
secp256k1_fe rx;
|
|
secp256k1_ge r;
|
|
unsigned char buf[32];
|
|
int overflow;
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
ARG_CHECK(sig64 != NULL);
|
|
ARG_CHECK(msg != NULL || msglen == 0);
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
if (!secp256k1_fe_set_b32_limit(&rx, &sig64[0])) {
|
|
return 0;
|
|
}
|
|
|
|
secp256k1_scalar_set_b32(&s, &sig64[32], &overflow);
|
|
if (overflow) {
|
|
return 0;
|
|
}
|
|
|
|
if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) {
|
|
return 0;
|
|
}
|
|
|
|
/* Compute e. */
|
|
secp256k1_fe_get_b32(buf, &pk.x);
|
|
secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf);
|
|
|
|
/* Compute rj = s*G + (-e)*pkj */
|
|
secp256k1_scalar_negate(&e, &e);
|
|
secp256k1_gej_set_ge(&pkj, &pk);
|
|
secp256k1_ecmult(&rj, &pkj, &e, &s);
|
|
|
|
secp256k1_ge_set_gej_var(&r, &rj);
|
|
if (secp256k1_ge_is_infinity(&r)) {
|
|
return 0;
|
|
}
|
|
|
|
secp256k1_fe_normalize_var(&r.y);
|
|
return !secp256k1_fe_is_odd(&r.y) &&
|
|
secp256k1_fe_equal(&rx, &r.x);
|
|
}
|
|
|
|
#endif
|