mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-10 09:06:15 +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
260 lines
11 KiB
C
260 lines
11 KiB
C
/*************************************************************************
|
|
* To the extent possible under law, the author(s) have dedicated all *
|
|
* copyright and related and neighboring rights to the software in this *
|
|
* file to the public domain worldwide. This software is distributed *
|
|
* without any warranty. For the CC0 Public Domain Dedication, see *
|
|
* EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *
|
|
*************************************************************************/
|
|
|
|
/** This file demonstrates how to use the MuSig module to create a
|
|
* 3-of-3 multisignature. Additionally, see the documentation in
|
|
* include/secp256k1_musig.h and doc/musig.md.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include <secp256k1.h>
|
|
#include <secp256k1_extrakeys.h>
|
|
#include <secp256k1_musig.h>
|
|
#include <secp256k1_schnorrsig.h>
|
|
|
|
#include "examples_util.h"
|
|
|
|
struct signer_secrets {
|
|
secp256k1_keypair keypair;
|
|
secp256k1_musig_secnonce secnonce;
|
|
};
|
|
|
|
struct signer {
|
|
secp256k1_pubkey pubkey;
|
|
secp256k1_musig_pubnonce pubnonce;
|
|
secp256k1_musig_partial_sig partial_sig;
|
|
};
|
|
|
|
/* Number of public keys involved in creating the aggregate signature */
|
|
#define N_SIGNERS 3
|
|
/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */
|
|
static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
|
|
unsigned char seckey[32];
|
|
|
|
if (!fill_random(seckey, sizeof(seckey))) {
|
|
printf("Failed to generate randomness\n");
|
|
return 0;
|
|
}
|
|
/* Try to create a keypair with a valid context. This only fails if the
|
|
* secret key is zero or out of range (greater than secp256k1's order). Note
|
|
* that the probability of this occurring is negligible with a properly
|
|
* functioning random number generator. */
|
|
if (!secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) {
|
|
return 0;
|
|
}
|
|
if (!secp256k1_keypair_pub(ctx, &signer->pubkey, &signer_secrets->keypair)) {
|
|
return 0;
|
|
}
|
|
|
|
secure_erase(seckey, sizeof(seckey));
|
|
return 1;
|
|
}
|
|
|
|
/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache
|
|
* and return the tweaked aggregate pk. */
|
|
static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) {
|
|
secp256k1_pubkey output_pk;
|
|
/* For BIP 32 tweaking the plain_tweak is set to a hash as defined in BIP
|
|
* 32. */
|
|
unsigned char plain_tweak[32] = "this could be a BIP32 tweak....";
|
|
/* For Taproot tweaking the xonly_tweak is set to the TapTweak hash as
|
|
* defined in BIP 341 */
|
|
unsigned char xonly_tweak[32] = "this could be a Taproot tweak..";
|
|
|
|
|
|
/* Plain tweaking which, for example, allows deriving multiple child
|
|
* public keys from a single aggregate key using BIP32 */
|
|
if (!secp256k1_musig_pubkey_ec_tweak_add(ctx, NULL, cache, plain_tweak)) {
|
|
return 0;
|
|
}
|
|
/* Note that we did not provide an output_pk argument, because the
|
|
* resulting pk is also saved in the cache and so if one is just interested
|
|
* in signing, the output_pk argument is unnecessary. On the other hand, if
|
|
* one is not interested in signing, the same output_pk can be obtained by
|
|
* calling `secp256k1_musig_pubkey_get` right after key aggregation to get
|
|
* the full pubkey and then call `secp256k1_ec_pubkey_tweak_add`. */
|
|
|
|
/* Xonly tweaking which, for example, allows creating Taproot commitments */
|
|
if (!secp256k1_musig_pubkey_xonly_tweak_add(ctx, &output_pk, cache, xonly_tweak)) {
|
|
return 0;
|
|
}
|
|
/* Note that if we wouldn't care about signing, we can arrive at the same
|
|
* output_pk by providing the untweaked public key to
|
|
* `secp256k1_xonly_pubkey_tweak_add` (after converting it to an xonly pubkey
|
|
* if necessary with `secp256k1_xonly_pubkey_from_pubkey`). */
|
|
|
|
/* Now we convert the output_pk to an xonly pubkey to allow to later verify
|
|
* the Schnorr signature against it. For this purpose we can ignore the
|
|
* `pk_parity` output argument; we would need it if we would have to open
|
|
* the Taproot commitment. */
|
|
if (!secp256k1_xonly_pubkey_from_pubkey(ctx, agg_pk, NULL, &output_pk)) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Sign a message hash with the given key pairs and store the result in sig */
|
|
static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) {
|
|
int i;
|
|
const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS];
|
|
const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS];
|
|
/* The same for all signers */
|
|
secp256k1_musig_session session;
|
|
secp256k1_musig_aggnonce agg_pubnonce;
|
|
|
|
for (i = 0; i < N_SIGNERS; i++) {
|
|
unsigned char seckey[32];
|
|
unsigned char session_secrand[32];
|
|
/* Create random session ID. It is absolutely necessary that the session ID
|
|
* is unique for every call of secp256k1_musig_nonce_gen. Otherwise
|
|
* it's trivial for an attacker to extract the secret key! */
|
|
if (!fill_random(session_secrand, sizeof(session_secrand))) {
|
|
return 0;
|
|
}
|
|
if (!secp256k1_keypair_sec(ctx, seckey, &signer_secrets[i].keypair)) {
|
|
return 0;
|
|
}
|
|
/* Initialize session and create secret nonce for signing and public
|
|
* nonce to send to the other signers. */
|
|
if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_secrand, seckey, &signer[i].pubkey, msg32, NULL, NULL)) {
|
|
return 0;
|
|
}
|
|
pubnonces[i] = &signer[i].pubnonce;
|
|
|
|
secure_erase(seckey, sizeof(seckey));
|
|
}
|
|
|
|
/* Communication round 1: Every signer sends their pubnonce to the
|
|
* coordinator. The coordinator runs secp256k1_musig_nonce_agg and sends
|
|
* agg_pubnonce to each signer */
|
|
if (!secp256k1_musig_nonce_agg(ctx, &agg_pubnonce, pubnonces, N_SIGNERS)) {
|
|
return 0;
|
|
}
|
|
|
|
/* Every signer creates a partial signature */
|
|
for (i = 0; i < N_SIGNERS; i++) {
|
|
/* Initialize the signing session by processing the aggregate nonce */
|
|
if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache)) {
|
|
return 0;
|
|
}
|
|
/* partial_sign will clear the secnonce by setting it to 0. That's because
|
|
* you must _never_ reuse the secnonce (or use the same session_secrand to
|
|
* create a secnonce). If you do, you effectively reuse the nonce and
|
|
* leak the secret key. */
|
|
if (!secp256k1_musig_partial_sign(ctx, &signer[i].partial_sig, &signer_secrets[i].secnonce, &signer_secrets[i].keypair, cache, &session)) {
|
|
return 0;
|
|
}
|
|
partial_sigs[i] = &signer[i].partial_sig;
|
|
}
|
|
/* Communication round 2: Every signer sends their partial signature to the
|
|
* coordinator, who verifies the partial signatures and aggregates them. */
|
|
for (i = 0; i < N_SIGNERS; i++) {
|
|
/* To check whether signing was successful, it suffices to either verify
|
|
* the aggregate signature with the aggregate public key using
|
|
* secp256k1_schnorrsig_verify, or verify all partial signatures of all
|
|
* signers individually. Verifying the aggregate signature is cheaper but
|
|
* verifying the individual partial signatures has the advantage that it
|
|
* can be used to determine which of the partial signatures are invalid
|
|
* (if any), i.e., which of the partial signatures cause the aggregate
|
|
* signature to be invalid and thus the protocol run to fail. It's also
|
|
* fine to first verify the aggregate sig, and only verify the individual
|
|
* sigs if it does not work.
|
|
*/
|
|
if (!secp256k1_musig_partial_sig_verify(ctx, &signer[i].partial_sig, &signer[i].pubnonce, &signer[i].pubkey, cache, &session)) {
|
|
return 0;
|
|
}
|
|
}
|
|
return secp256k1_musig_partial_sig_agg(ctx, sig64, &session, partial_sigs, N_SIGNERS);
|
|
}
|
|
|
|
int main(void) {
|
|
secp256k1_context* ctx;
|
|
int i;
|
|
struct signer_secrets signer_secrets[N_SIGNERS];
|
|
struct signer signers[N_SIGNERS];
|
|
const secp256k1_pubkey *pubkeys_ptr[N_SIGNERS];
|
|
secp256k1_xonly_pubkey agg_pk;
|
|
secp256k1_musig_keyagg_cache cache;
|
|
unsigned char msg[32] = "this_could_be_the_hash_of_a_msg";
|
|
unsigned char sig[64];
|
|
|
|
/* Create a secp256k1 context */
|
|
ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
|
printf("Creating key pairs......");
|
|
fflush(stdout);
|
|
for (i = 0; i < N_SIGNERS; i++) {
|
|
if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
pubkeys_ptr[i] = &signers[i].pubkey;
|
|
}
|
|
printf("ok\n");
|
|
|
|
/* The aggregate public key produced by secp256k1_musig_pubkey_agg depends
|
|
* on the order of the provided public keys. If there is no canonical order
|
|
* of the signers, the individual public keys can optionally be sorted with
|
|
* secp256k1_ec_pubkey_sort to ensure that the aggregate public key is
|
|
* independent of the order of signers. */
|
|
printf("Sorting public keys.....");
|
|
fflush(stdout);
|
|
if (!secp256k1_ec_pubkey_sort(ctx, pubkeys_ptr, N_SIGNERS)) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
printf("ok\n");
|
|
|
|
printf("Combining public keys...");
|
|
fflush(stdout);
|
|
/* If you just want to aggregate and not sign, you can call
|
|
* secp256k1_musig_pubkey_agg with the keyagg_cache argument set to NULL
|
|
* while providing a non-NULL agg_pk argument. */
|
|
if (!secp256k1_musig_pubkey_agg(ctx, NULL, &cache, pubkeys_ptr, N_SIGNERS)) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
printf("ok\n");
|
|
printf("Tweaking................");
|
|
fflush(stdout);
|
|
/* Optionally tweak the aggregate key */
|
|
if (!tweak(ctx, &agg_pk, &cache)) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
printf("ok\n");
|
|
printf("Signing message.........");
|
|
fflush(stdout);
|
|
if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
printf("ok\n");
|
|
printf("Verifying signature.....");
|
|
fflush(stdout);
|
|
if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) {
|
|
printf("FAILED\n");
|
|
return 1;
|
|
}
|
|
printf("ok\n");
|
|
|
|
/* It's best practice to try to clear secrets from memory after using them.
|
|
* This is done because some bugs can allow an attacker to leak memory, for
|
|
* example through "out of bounds" array access (see Heartbleed), or the OS
|
|
* swapping them to disk. Hence, we overwrite secret key material with zeros.
|
|
*
|
|
* Here we are preventing these writes from being optimized out, as any good compiler
|
|
* will remove any writes that aren't used. */
|
|
for (i = 0; i < N_SIGNERS; i++) {
|
|
secure_erase(&signer_secrets[i], sizeof(signer_secrets[i]));
|
|
}
|
|
secp256k1_context_destroy(ctx);
|
|
return 0;
|
|
}
|