musig: replace MuSig(1) with MuSig2

This commit is contained in:
Jonas Nick 2021-05-05 15:45:31 +00:00
parent e290c0f835
commit 22c88815c7
15 changed files with 2886 additions and 2256 deletions

2
.gitignore vendored
View File

@ -64,3 +64,5 @@ build-aux/test-driver
src/stamp-h1
libsecp256k1.pc
contrib/gh-pr-create.sh
example_musig

View File

@ -129,6 +129,15 @@ exhaustive_tests_LDFLAGS = -static
TESTS += exhaustive_tests
endif
if ENABLE_MODULE_MUSIG
noinst_PROGRAMS += example_musig
example_musig_SOURCES = examples/musig.c
example_musig_CPPFLAGS = -I$(top_srcdir)/include
example_musig_LDADD = libsecp256k1.la
example_musig_LDFLAGS = -static
TESTS += example_musig
endif
EXTRA_PROGRAMS = gen_ecmult_static_pre_g
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
# See Automake manual, Section "Errors with distclean"

178
examples/musig.c Normal file
View File

@ -0,0 +1,178 @@
/***********************************************************************
* Copyright (c) 2018 Jonas Nick *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
/**
* This file demonstrates how to use the MuSig module to create a multisignature.
* Additionally, see the documentation in include/secp256k1_musig.h.
*/
#include <stdio.h>
#include <assert.h>
#include <secp256k1.h>
#include <secp256k1_schnorrsig.h>
#include <secp256k1_musig.h>
struct signer_secrets {
secp256k1_keypair keypair;
secp256k1_musig_secnonce secnonce;
};
struct signer {
secp256k1_xonly_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 */
int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
unsigned char seckey[32];
FILE *frand = fopen("/dev/urandom", "r");
if (frand == NULL) {
return 0;
}
do {
if(!fread(seckey, sizeof(seckey), 1, frand)) {
fclose(frand);
return 0;
}
/* The probability that this not a valid secret key is approximately 2^-128 */
} while (!secp256k1_ec_seckey_verify(ctx, seckey));
fclose(frand);
if (!secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) {
return 0;
}
if (!secp256k1_keypair_xonly_pub(ctx, &signer->pubkey, NULL, &signer_secrets->keypair)) {
return 0;
}
return 1;
}
/* Sign a message hash with the given key pairs and store the result in sig */
int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const unsigned char* msg32, unsigned char *sig64) {
int i;
const secp256k1_xonly_pubkey *pubkeys[N_SIGNERS];
const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS];
const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS];
/* The same for all signers */
secp256k1_musig_keyagg_cache cache;
secp256k1_musig_session session;
for (i = 0; i < N_SIGNERS; i++) {
FILE *frand;
unsigned char seckey[32];
unsigned char session_id[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! */
frand = fopen("/dev/urandom", "r");
if(frand == NULL) {
return 0;
}
if (!fread(session_id, 32, 1, frand)) {
fclose(frand);
return 0;
}
fclose(frand);
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_id, seckey, msg32, NULL, NULL)) {
return 0;
}
pubkeys[i] = &signer[i].pubkey;
pubnonces[i] = &signer[i].pubnonce;
}
/* Communication round 1: A production system would exchange public nonces
* here before moving on. */
for (i = 0; i < N_SIGNERS; i++) {
secp256k1_musig_aggnonce agg_pubnonce;
/* Create aggregate pubkey, aggregate nonce and initialize signer data */
if (!secp256k1_musig_pubkey_agg(ctx, NULL, NULL, &cache, pubkeys, N_SIGNERS)) {
return 0;
}
if (!secp256k1_musig_nonce_agg(ctx, &agg_pubnonce, pubnonces, N_SIGNERS)) {
return 0;
}
if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, &cache, NULL)) {
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_id 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: A production system would exchange
* partial signatures here before moving on. */
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_xonly_pubkey *pubkeys_ptr[N_SIGNERS];
secp256k1_xonly_pubkey agg_pk;
unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!";
unsigned char sig[64];
/* Create a context for signing and verification */
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
printf("Creating key pairs......");
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");
printf("Combining public keys...");
if (!secp256k1_musig_pubkey_agg(ctx, NULL, &agg_pk, NULL, pubkeys_ptr, N_SIGNERS)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
printf("Signing message.........");
if (!sign(ctx, signer_secrets, signers, msg, sig)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
printf("Verifying signature.....");
if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
secp256k1_context_destroy(ctx);
return 0;
}

View File

@ -7,364 +7,169 @@
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
/** This module implements a Schnorr-based multi-signature scheme called MuSig
* (https://eprint.iacr.org/2018/068.pdf). It is compatible with bip-schnorr.
/** This module implements a Schnorr-based multi-signature scheme called MuSig2
* (https://eprint.iacr.org/2020/1261, see Appendix B for the exact variant).
* Signatures are compatible with BIP-340 ("Schnorr").
* There's an example C source file in the module's directory
* (src/modules/musig/example.c) that demonstrates how it can be used.
* (examples/musig.c) that demonstrates how it can be used.
*
* The documentation in this include file is for reference and may not be sufficient
* for users to begin using the library. A full description of API usage can be found
* in src/modules/musig/musig.md
* The module also supports BIP-341 ("Taproot") public key tweaking and adaptor
* signatures as described in
* https://github.com/ElementsProject/scriptless-scripts/pull/24.
*
* It is recommended to read the documentation in this include file carefully.
* Further notes on API usage can be found in src/modules/musig/musig.md
*
* You may know that the MuSig2 scheme uses two "nonces" instead of one. This
* is not wrong, but only a technical detail we don't want to bother the user
* with. Therefore, the API only uses the singular term "nonce".
*
* Since the first version of MuSig is essentially replaced by MuSig2, when
* writing MuSig or musig here we mean MuSig2.
*/
/** Data structure containing auxiliary data generated in `pubkey_combine` and
* required for `session_*_init`.
* Fields:
* magic: Set during initialization in `pubkey_combine` to allow
* detecting an uninitialized object.
* pk_hash: The 32-byte hash of the original public keys
* second_pk: Serialized x-coordinate of the second public key in the list.
* Filled with zeros if there is none.
* pk_parity: Whether the MuSig-aggregated point was negated when
* converting it to the combined xonly pubkey.
* is_tweaked: Whether the combined pubkey was tweaked
* tweak: If is_tweaked, array with the 32-byte tweak
* internal_key_parity: If is_tweaked, the parity of the combined pubkey
* before tweaking
*/
typedef struct {
uint64_t magic;
unsigned char pk_hash[32];
unsigned char second_pk[32];
int pk_parity;
int is_tweaked;
unsigned char tweak[32];
int internal_key_parity;
} secp256k1_musig_pre_session;
/** Data structure containing data related to a signing session resulting in a single
* signature.
*
* This structure is not opaque, but it MUST NOT be copied or read or written to it
* directly. A signer who is online throughout the whole process and can keep this
* structure in memory can use the provided API functions for a safe standard
* workflow. See https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/
* for more details about the risks associated with serializing or deserializing this
* structure.
*
* Fields:
* magic: Set in `musig_session_init` to allow detecting an
* uninitialized object.
* round: Current round of the session
* pre_session: Auxiliary data created in `pubkey_combine`
* combined_pk: MuSig-computed combined xonly public key
* n_signers: Number of signers
* msg: The 32-byte message (hash) to be signed
* is_msg_set: Whether the above message has been set
* has_secret_data: Whether this session object has a signers' secret data; if this
* is `false`, it may still be used for verification purposes.
* seckey: If `has_secret_data`, the signer's secret key
* secnonce: If `has_secret_data`, the signer's secret nonce
* nonce: If `has_secret_data`, the signer's public nonce
* nonce_commitments_hash: If `has_secret_data` and round >= 1, the hash of all
* signers' commitments
* combined_nonce: If round >= 2, the summed combined public nonce
* combined_nonce_parity: If round >= 2, the parity of the Y coordinate of above
* nonce.
*/
typedef struct {
uint64_t magic;
int round;
secp256k1_musig_pre_session pre_session;
secp256k1_xonly_pubkey combined_pk;
uint32_t n_signers;
int is_msg_set;
unsigned char msg[32];
int has_secret_data;
unsigned char seckey[32];
unsigned char secnonce[32];
secp256k1_xonly_pubkey nonce;
int partial_nonce_parity;
unsigned char nonce_commitments_hash[32];
secp256k1_xonly_pubkey combined_nonce;
int combined_nonce_parity;
} secp256k1_musig_session;
/** Data structure containing data on all signers in a single session.
*
* The workflow for this structure is as follows:
*
* 1. This structure is initialized with `musig_session_init` or
* `musig_session_init_verifier`, which initializes
* all other fields. The public session is initialized with the signers'
* nonce_commitments.
*
* 2. In a non-public session the nonce_commitments are set with the function
* `musig_get_public_nonce`, which also returns the signer's public nonce. This
* ensures that the public nonce is not exposed until all commitments have been
* received.
*
* 3. Each individual data struct should be updated with `musig_set_nonce` once a
* nonce is available. This function takes a single signer data struct rather than
* an array because it may fail in the case that the provided nonce does not match
* the commitment. In this case, it is desirable to identify the exact party whose
* nonce was inconsistent.
*
* Fields:
* present: indicates whether the signer's nonce is set
* nonce: public nonce, must be a valid curvepoint if the signer is `present`
* nonce_commitment: commitment to the nonce, or all-bits zero if a commitment
* has not yet been set
*/
typedef struct {
int present;
secp256k1_xonly_pubkey nonce;
unsigned char nonce_commitment[32];
} secp256k1_musig_session_signer_data;
/** Opaque data structure that holds a MuSig partial signature.
/** Opaque data structures
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is however
* guaranteed to be 32 bytes in size, and can be safely copied/moved. If you need
* to convert to a format suitable for storage, transmission, or comparison, use the
* `musig_partial_signature_serialize` and `musig_partial_signature_parse`
* functions.
* guaranteed to be portable between different platforms or versions. If you
* need to convert to a format suitable for storage, transmission, or
* comparison, use the corresponding serialization and parsing functions.
*/
/** Opaque data structure that caches information about public key aggregation.
*
* Guaranteed to be 165 bytes in size. It can be safely copied/moved. No
* serialization and parsing functions (yet).
*/
typedef struct {
unsigned char data[32];
} secp256k1_musig_partial_signature;
unsigned char data[165];
} secp256k1_musig_keyagg_cache;
/** Computes a combined public key and the hash of the given public keys.
/** Opaque data structure that holds a signer's _secret_ nonce.
*
* Different orders of `pubkeys` result in different `combined_pk`s.
* Guaranteed to be 68 bytes in size.
*
* The pubkeys can be sorted before combining with `secp256k1_xonly_sort` which
* ensures the same resulting `combined_pk` for the same multiset of pubkeys.
* This is useful to do before pubkey_combine, such that the order of pubkeys
* does not affect the combined public key.
* WARNING: This structure MUST NOT be copied or read or written to directly. A
* signer who is online throughout the whole process and can keep this
* structure in memory can use the provided API functions for a safe standard
* workflow. See
* https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/ for
* more details about the risks associated with serializing or deserializing
* this structure.
*
* Returns: 1 if the public keys were successfully combined, 0 otherwise
* Args: ctx: pointer to a context object initialized for verification
* (cannot be NULL)
* scratch: scratch space used to compute the combined pubkey by
* multiexponentiation. If NULL, an inefficient algorithm is used.
* Out: combined_pk: the MuSig-combined xonly public key (cannot be NULL)
* pre_session: if non-NULL, pointer to a musig_pre_session struct to be used in
* `musig_session_init` or `musig_pubkey_tweak_add`.
* In: pubkeys: input array of pointers to public keys to combine. The order
* is important; a different order will result in a different
* combined public key (cannot be NULL)
* n_pubkeys: length of pubkeys array. Must be greater than 0.
* We repeat, copying this data structure can result in nonce reuse which will
* leak the secret signing key.
*/
SECP256K1_API int secp256k1_musig_pubkey_combine(
const secp256k1_context* ctx,
secp256k1_scratch_space *scratch,
secp256k1_xonly_pubkey *combined_pk,
secp256k1_musig_pre_session *pre_session,
const secp256k1_xonly_pubkey * const* pubkeys,
size_t n_pubkeys
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
typedef struct {
unsigned char data[68];
} secp256k1_musig_secnonce;
/** Tweak an x-only public key by adding the generator multiplied with tweak32
* to it. The resulting output_pubkey with the given internal_pubkey and tweak
* passes `secp256k1_xonly_pubkey_tweak_test`.
*
* This function is only useful before initializing a signing session. If you
* are only computing a public key, but not intending to create a signature for
* it, you can just use `secp256k1_xonly_pubkey_tweak_add`. Can only be called
* once with a given pre_session.
*
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
* Args: ctx: pointer to a context object initialized for verification
* (cannot be NULL)
* pre_session: pointer to a `musig_pre_session` struct initialized in
* `musig_pubkey_combine` (cannot be NULL)
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0 (cannot
* be NULL)
* In: internal_pubkey: pointer to the `combined_pk` from
* `musig_pubkey_combine` to which the tweak is applied.
* (cannot be NULL).
* tweak32: pointer to a 32-byte tweak. If the tweak is invalid
* according to secp256k1_ec_seckey_verify, this function
* returns 0. For uniformly random 32-byte arrays the
* chance of being invalid is negligible (around 1 in
* 2^128) (cannot be NULL).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
const secp256k1_context* ctx,
secp256k1_musig_pre_session *pre_session,
secp256k1_pubkey *output_pubkey,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Opaque data structure that holds a signer's public nonce.
*
* Guaranteed to be 132 bytes in size. It can be safely copied/moved. Serialized
* and parsed with `musig_pubnonce_serialize` and `musig_pubnonce_parse`.
*/
typedef struct {
unsigned char data[132];
} secp256k1_musig_pubnonce;
/** Initializes a signing session for a signer
/** Opaque data structure that holds an aggregate public nonce.
*
* Returns: 1: session is successfully initialized
* 0: session could not be initialized: secret key or secret nonce overflow
* Args: ctx: pointer to a context object, initialized for signing (cannot
* be NULL)
* Out: session: the session structure to initialize (cannot be NULL)
* signers: an array of signers' data to be initialized. Array length must
* equal to `n_signers` (cannot be NULL)
* nonce_commitment32: filled with a 32-byte commitment to the generated nonce
* (cannot be NULL)
* In: session_id32: a *unique* 32-byte ID to assign to this session (cannot be
* NULL). If a non-unique session_id32 was given then a partial
* signature will LEAK THE SECRET KEY.
* msg32: the 32-byte message to be signed. Shouldn't be NULL unless you
* require sharing nonce commitments before the message is known
* because it reduces nonce misuse resistance. If NULL, must be
* set with `musig_session_get_public_nonce`.
* combined_pk: the combined xonly public key of all signers (cannot be NULL)
* pre_session: pointer to a musig_pre_session struct after initializing
* it with `musig_pubkey_combine` and optionally provided to
* `musig_pubkey_tweak_add` (cannot be NULL).
* n_signers: length of signers array. Number of signers participating in
* the MuSig. Must be greater than 0 and at most 2^32 - 1.
* seckey: the signer's 32-byte secret key (cannot be NULL)
* Guaranteed to be 132 bytes in size. It can be safely copied/moved.
* Serialized and parsed with `musig_aggnonce_serialize` and
* `musig_aggnonce_parse`.
*/
SECP256K1_API int secp256k1_musig_session_init(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers,
unsigned char *nonce_commitment32,
const unsigned char *session_id32,
const unsigned char *msg32,
const secp256k1_xonly_pubkey *combined_pk,
const secp256k1_musig_pre_session *pre_session,
size_t n_signers,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8) SECP256K1_ARG_NONNULL(10);
typedef struct {
unsigned char data[132];
} secp256k1_musig_aggnonce;
/** Gets the signer's public nonce given a list of all signers' data with
* commitments. Called by participating signers after
* `secp256k1_musig_session_init` and after all nonce commitments have
* been collected
/** Opaque data structure that holds a MuSig session.
*
* Returns: 1: public nonce is written in nonce
* 0: signer data is missing commitments or session isn't initialized
* for signing
* Args: ctx: pointer to a context object (cannot be NULL)
* session: the signing session to get the nonce from (cannot be NULL)
* signers: an array of signers' data initialized with
* `musig_session_init`. Array length must equal to
* `n_commitments` (cannot be NULL)
* Out: nonce32: filled with a 32-byte public nonce which is supposed to be
* sent to the other signers and then used in `musig_set nonce`
* (cannot be NULL)
* In: commitments: array of pointers to 32-byte nonce commitments (cannot be NULL)
* n_commitments: the length of commitments and signers array. Must be the total
* number of signers participating in the MuSig.
* msg32: the 32-byte message to be signed. Must be NULL if already
* set with `musig_session_init` otherwise can not be NULL.
* This structure is not required to be kept secret for the signing protocol to
* be secure. Guaranteed to be 133 bytes in size. It can be safely
* copied/moved. No serialization and parsing functions (yet).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_public_nonce(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers,
unsigned char *nonce32,
const unsigned char *const *commitments,
size_t n_commitments,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
typedef struct {
unsigned char data[133];
} secp256k1_musig_session;
/** Initializes a verifier session that can be used for verifying nonce commitments
* and partial signatures. It does not have secret key material and therefore can not
* be used to create signatures.
/** Opaque data structure that holds a partial MuSig signature.
*
* Returns: 1 when session is successfully initialized, 0 otherwise
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: session: the session structure to initialize (cannot be NULL)
* signers: an array of signers' data to be initialized. Array length must
* equal to `n_signers`(cannot be NULL)
* In: msg32: the 32-byte message to be signed (cannot be NULL)
* combined_pk: the combined xonly public key of all signers (cannot be NULL)
* pre_session: pointer to a musig_pre_session struct from
* `musig_pubkey_combine` (cannot be NULL)
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be NULL)
* commitments: array of pointers to 32-byte nonce commitments. Array
* length must equal to `n_signers` (cannot be NULL)
* n_signers: length of signers and commitments array. Number of signers
* participating in the MuSig. Must be greater than 0 and at most
* 2^32 - 1.
* Guaranteed to be 36 bytes in size. Serialized and parsed with
* `musig_partial_sig_serialize` and `musig_partial_sig_parse`.
*/
SECP256K1_API int secp256k1_musig_session_init_verifier(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers,
const unsigned char *msg32,
const secp256k1_xonly_pubkey *combined_pk,
const secp256k1_musig_pre_session *pre_session,
const unsigned char *const *commitments,
size_t n_signers
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7);
typedef struct {
unsigned char data[36];
} secp256k1_musig_partial_sig;
/** Checks a signer's public nonce against a commitment to said nonce, and update
* data structure if they match
/** Parse a signer's public nonce.
*
* Returns: 1: commitment was valid, data structure updated
* 0: commitment was invalid, nothing happened
* Args: ctx: pointer to a context object (cannot be NULL)
* signer: pointer to the signer data to update (cannot be NULL). Must have
* been used with `musig_session_get_public_nonce` or initialized
* with `musig_session_init_verifier`.
* In: nonce32: signer's alleged public nonce (cannot be NULL)
* Returns: 1 when the nonce could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: nonce: pointer to a nonce object
* In: in66: pointer to the 66-byte nonce to be parsed
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_set_nonce(
SECP256K1_API int secp256k1_musig_pubnonce_parse(
const secp256k1_context* ctx,
secp256k1_musig_session_signer_data *signer,
const unsigned char *nonce32
secp256k1_musig_pubnonce* nonce,
const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Updates a session with the combined public nonce of all signers. The combined
* public nonce is the sum of every signer's public nonce.
/** Serialize a signer's public nonce
*
* Returns: 1: nonces are successfully combined
* 0: a signer's nonce is missing
* Args: ctx: pointer to a context object (cannot be NULL)
* session: session to update with the combined public nonce (cannot be
* NULL)
* signers: an array of signers' data, which must have had public nonces
* set with `musig_set_nonce`. Array length must equal to `n_signers`
* (cannot be NULL)
* n_signers: the length of the signers array. Must be the total number of
* signers participating in the MuSig.
* Out: nonce_parity: if non-NULL, a pointer to an integer that indicates the
* parity of the combined public nonce. Used for adaptor
* signatures.
* adaptor: point to add to the combined public nonce. If NULL, nothing is
* added to the combined nonce.
* Returns: 1 when the nonce could be serialized, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: out66: pointer to a 66-byte array to store the serialized nonce
* In: nonce: pointer to the nonce
*/
SECP256K1_API int secp256k1_musig_session_combine_nonces(
SECP256K1_API int secp256k1_musig_pubnonce_serialize(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
const secp256k1_musig_session_signer_data *signers,
size_t n_signers,
int *nonce_parity,
const secp256k1_pubkey *adaptor
unsigned char *out66,
const secp256k1_musig_pubnonce* nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a MuSig partial signature or adaptor signature
/** Parse an aggregate public nonce.
*
* Returns: 1 when the nonce could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: nonce: pointer to a nonce object
* In: in66: pointer to the 66-byte nonce to be parsed
*/
SECP256K1_API int secp256k1_musig_aggnonce_parse(
const secp256k1_context* ctx,
secp256k1_musig_aggnonce* nonce,
const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an aggregate public nonce
*
* Returns: 1 when the nonce could be serialized, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: out66: pointer to a 66-byte array to store the serialized nonce
* In: nonce: pointer to the nonce
*/
SECP256K1_API int secp256k1_musig_aggnonce_serialize(
const secp256k1_context* ctx,
unsigned char *out66,
const secp256k1_musig_aggnonce* nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a MuSig partial signature
*
* Returns: 1 when the signature could be serialized, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: out32: pointer to a 32-byte array to store the serialized signature
* In: sig: pointer to the signature
*/
SECP256K1_API int secp256k1_musig_partial_signature_serialize(
SECP256K1_API int secp256k1_musig_partial_sig_serialize(
const secp256k1_context* ctx,
unsigned char *out32,
const secp256k1_musig_partial_signature* sig
const secp256k1_musig_partial_sig* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse and verify a MuSig partial signature.
/** Parse a MuSig partial signature.
*
* Returns: 1 when the signature could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
@ -375,113 +180,337 @@ SECP256K1_API int secp256k1_musig_partial_signature_serialize(
* encoded numbers are out of range, signature verification with it is
* guaranteed to fail for every message and public key.
*/
SECP256K1_API int secp256k1_musig_partial_signature_parse(
SECP256K1_API int secp256k1_musig_partial_sig_parse(
const secp256k1_context* ctx,
secp256k1_musig_partial_signature* sig,
secp256k1_musig_partial_sig* sig,
const unsigned char *in32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Computes an aggregate public key and uses it to initialize a keyagg_cache
*
* Different orders of `pubkeys` result in different `agg_pk`s.
*
* The pubkeys can be sorted before combining with `secp256k1_xonly_sort` which
* ensures the same `agg_pk` result for the same multiset of pubkeys.
* This is useful to do before `pubkey_agg`, such that the order of pubkeys
* does not affect the aggregate public key.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object initialized for verification
* scratch: scratch space used to compute the aggregate pubkey by
* multiexponentiation. Generally, the larger the scratch
* space, the faster this function. However, the returns of
* providing a larger scratch space are diminishing. If NULL,
* an inefficient algorithm is used.
* Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it,
* this arg can be NULL.
* keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that
* is required for signing (or observing the signing session
* and verifying partial signatures).
* In: pubkeys: input array of pointers to public keys to aggregate. The order
* is important; a different order will result in a different
* aggregate public key.
* n_pubkeys: length of pubkeys array. Must be greater than 0.
*/
SECP256K1_API int secp256k1_musig_pubkey_agg(
const secp256k1_context* ctx,
secp256k1_scratch_space *scratch,
secp256k1_xonly_pubkey *agg_pk,
secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_xonly_pubkey * const* pubkeys,
size_t n_pubkeys
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(5);
/** Tweak an x-only public key in a given keyagg_cache by adding
* the generator multiplied with `tweak32` to it.
*
* The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in
* the following pseudocode xonly_pubkey_tweak_add_check (absent earlier
* failures) returns 1.
*
* secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...)
* secp256k1_musig_pubkey_tweak_add(..., output_pubkey, tweak32, keyagg_cache)
* secp256k1_xonly_pubkey_serialize(..., buf, output_pubkey)
* secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32)
*
* This function is required if you want to _sign_ for a tweaked aggregate key.
* On the other hand, if you are only computing a public key, but not intending
* to create a signature for it, you can just use
* `secp256k1_xonly_pubkey_tweak_add`.
*
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
* Args: ctx: pointer to a context object initialized for verification
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0. If you
* do not need it, this arg can be NULL.
* In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
* `musig_pubkey_agg`
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid
* according to secp256k1_ec_seckey_verify, this function
* returns 0. For uniformly random 32-byte arrays the
* chance of being invalid is negligible (around 1 in
* 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
const secp256k1_context* ctx,
secp256k1_pubkey *output_pubkey,
secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Starts a signing session by generating a nonce
*
* This function outputs a secret nonce that will be required for signing and a
* corresponding public nonce that is intended to be sent to other signers.
*
* MuSig differs from regular Schnorr signing in that implementers _must_ take
* special care to not reuse a nonce. This can be ensured by following these rules:
*
* 1. Each call to this function must have a UNIQUE session_id32 that must NOT BE
* REUSED in subsequent calls to this function.
* If you do not provide a seckey, session_id32 _must_ be UNIFORMLY RANDOM
* AND KEPT SECRET (even from other signers). If you do provide a seckey,
* session_id32 can instead be a counter (that must never repeat!). However,
* it is recommended to always choose session_id32 uniformly at random.
* 2. If you already know the seckey, message or aggregate public key
* cache, they can be optionally provided to derive the nonce and increase
* misuse-resistance. The extra_input32 argument can be used to provide
* additional data that does not repeat in normal scenarios, such as the
* current time.
* 3. Avoid copying (or serializing) the secnonce. This reduces the possibility
* that it is used more than once for signing.
*
* Remember that nonce reuse will leak the secret key!
* Note that using the same seckey for multiple MuSig sessions is fine.
*
* Returns: 0 if the arguments are invalid and 1 otherwise
* Args: ctx: pointer to a context object, initialized for signing
* Out: secnonce: pointer to a structure to store the secret nonce
* pubnonce: pointer to a structure to store the public nonce
* In: session_id32: a 32-byte session_id32 as explained above. Must be unique to this
* call to secp256k1_musig_nonce_gen and must be uniformly random
* unless you really know what you are doing.
* seckey: the 32-byte secret key that will later be used for signing, if
* already known (can be NULL)
* msg32: the 32-byte message that will later be signed, if already known
* (can be NULL)
* keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate
* (and potentially tweaked) public key if already known
* (can be NULL)
* extra_input32: an optional 32-byte array that is input to the nonce
* derivation function (can be NULL)
*/
SECP256K1_API int secp256k1_musig_nonce_gen(
const secp256k1_context* ctx,
secp256k1_musig_secnonce *secnonce,
secp256k1_musig_pubnonce *pubnonce,
const unsigned char *session_id32,
const unsigned char *seckey,
const unsigned char *msg32,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *extra_input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Aggregates the nonces of all signers into a single nonce
*
* This can be done by an untrusted party to reduce the communication
* between signers. Instead of everyone sending nonces to everyone else, there
* can be one party receiving all nonces, aggregating the nonces with this
* function and then sending only the aggregate nonce back to the signers.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: aggnonce: pointer to an aggregate public nonce object for
* musig_nonce_process
* In: pubnonces: array of pointers to public nonces sent by the
* signers
* n_pubnonces: number of elements in the pubnonces array. Must be
* greater than 0.
*/
SECP256K1_API int secp256k1_musig_nonce_agg(
const secp256k1_context* ctx,
secp256k1_musig_aggnonce *aggnonce,
const secp256k1_musig_pubnonce * const* pubnonces,
size_t n_pubnonces
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Takes the public nonces of all signers and computes a session that is
* required for signing and verification of partial signatures.
*
* If the adaptor argument is non-NULL, then the output of
* musig_partial_sig_agg will be a pre-signature which is not a valid Schnorr
* signature. In order to create a valid signature, the pre-signature and the
* secret adaptor must be provided to `musig_adapt`.
*
* Returns: 0 if the arguments are invalid or if some signer sent invalid
* pubnonces, 1 otherwise
* Args: ctx: pointer to a context object, initialized for verification
* Out: session: pointer to a struct to store the session
* In: aggnonce: pointer to an aggregate public nonce object that is the
* output of musig_nonce_agg
* msg32: the 32-byte message to sign
* keyagg_cache: pointer to the keyagg_cache that was used to create the
* aggregate (and potentially tweaked) pubkey
* adaptor: optional pointer to an adaptor point encoded as a public
* key if this signing session is part of an adaptor
* signature protocol (can be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process(
const secp256k1_context* ctx,
secp256k1_musig_session *session,
const secp256k1_musig_aggnonce *aggnonce,
const unsigned char *msg32,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_pubkey *adaptor
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Produces a partial signature
*
* Returns: 1: partial signature constructed
* 0: session in incorrect or inconsistent state
* Args: ctx: pointer to a context object (cannot be NULL)
* session: active signing session for which the combined nonce has been
* computed (cannot be NULL)
* Out: partial_sig: partial signature (cannot be NULL)
* This function overwrites the given secnonce with zeros and will abort if given a
* secnonce that is all zeros. This is a best effort attempt to protect against nonce
* reuse. However, this is of course easily defeated if the secnonce has been
* copied (or serialized). Remember that nonce reuse will leak the secret key!
*
* Returns: 0 if the arguments are invalid or the provided secnonce has already
* been used for signing, 1 otherwise
* Args: ctx: pointer to a context object
* Out: partial_sig: pointer to struct to store the partial signature
* In/Out: secnonce: pointer to the secnonce struct created in
* musig_nonce_gen that has been never used in a
* partial_sign call before
* In: keypair: pointer to keypair to sign the message with
* keyagg_cache: pointer to the keyagg_cache that was output when the
* aggregate public key for this session
* session: pointer to the session that was created with
* musig_nonce_process
*/
SECP256K1_API int secp256k1_musig_partial_sign(
const secp256k1_context* ctx,
const secp256k1_musig_session *session,
secp256k1_musig_partial_signature *partial_sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
secp256k1_musig_partial_sig *partial_sig,
secp256k1_musig_secnonce *secnonce,
const secp256k1_keypair *keypair,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_musig_session *session
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
/** Checks that an individual partial signature verifies
/** Verifies an individual signer's partial signature
*
* This function is essential when using protocols with adaptor signatures.
* However, it is not essential for regular MuSig's, in the sense that if any
* partial signatures does not verify, the full signature will also not verify, so the
* However, it is not essential for regular MuSig sessions, in the sense that if any
* partial signature does not verify, the full signature will not verify either, so the
* problem will be caught. But this function allows determining the specific party
* who produced an invalid signature, so that signing can be restarted without them.
* who produced an invalid signature.
*
* Returns: 1: partial signature verifies
* 0: invalid signature or bad data
* Args: ctx: pointer to a context object (cannot be NULL)
* session: active session for which the combined nonce has been computed
* (cannot be NULL)
* signer: data for the signer who produced this signature (cannot be NULL)
* In: partial_sig: signature to verify (cannot be NULL)
* pubkey: public key of the signer who produced the signature (cannot be NULL)
* Returns: 0 if the arguments are invalid or the partial signature does not
* verify, 1 otherwise
* Args ctx: pointer to a context object, initialized for verification
* In: partial_sig: pointer to partial signature to verify
* pubnonce: public nonce sent by the signer who produced the signature
* pubkey: public key of the signer who produced the signature
* keyagg_cache: pointer to the keyagg_cache that was output when the
* aggregate public key for this session
* session: pointer to the session that was created with
* musig_nonce_process
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify(
const secp256k1_context* ctx,
const secp256k1_musig_session *session,
const secp256k1_musig_session_signer_data *signer,
const secp256k1_musig_partial_signature *partial_sig,
const secp256k1_xonly_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
const secp256k1_musig_partial_sig *partial_sig,
const secp256k1_musig_pubnonce *pubnonce,
const secp256k1_xonly_pubkey *pubkey,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_musig_session *session
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
/** Combines partial signatures
/** Aggregates partial signatures
*
* Returns: 1: all partial signatures have values in range. Does NOT mean the
* resulting signature verifies.
* 0: some partial signature are missing or had s or r out of range
* Args: ctx: pointer to a context object (cannot be NULL)
* session: initialized session for which the combined nonce has been
* computed (cannot be NULL)
* Out: sig64: complete signature (cannot be NULL)
* In: partial_sigs: array of partial signatures to combine (cannot be NULL)
* n_sigs: number of signatures in the partial_sigs array
* Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean
* the resulting signature verifies).
* Args: ctx: pointer to a context object
* Out: sig64: complete (but possibly invalid) Schnorr signature
* In: session: pointer to the session that was created with
* musig_nonce_process
* partial_sigs: array of pointers to partial signatures to aggregate
* n_sigs: number of elements in the partial_sigs array. Must be
* greater than 0.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_combine(
SECP256K1_API int secp256k1_musig_partial_sig_agg(
const secp256k1_context* ctx,
const secp256k1_musig_session *session,
unsigned char *sig64,
const secp256k1_musig_partial_signature *partial_sigs,
const secp256k1_musig_session *session,
const secp256k1_musig_partial_sig * const* partial_sigs,
size_t n_sigs
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Converts a partial signature to an adaptor signature by adding a given secret
* adaptor.
/** Extracts the nonce_parity bit from a session
*
* Returns: 1: signature and secret adaptor contained valid values
* 0: otherwise
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: adaptor_sig: adaptor signature to produce (cannot be NULL)
* In: partial_sig: partial signature to tweak with secret adaptor (cannot be NULL)
* sec_adaptor32: 32-byte secret adaptor to add to the partial signature (cannot
* be NULL)
* nonce_parity: the `nonce_parity` output of `musig_session_combine_nonces`
* This is used for adaptor signatures.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: nonce_parity: pointer to an integer that indicates the parity
* of the aggregate public nonce. Used for adaptor
* signatures.
* In: session: pointer to the session that was created with
* musig_nonce_process
*/
SECP256K1_API int secp256k1_musig_partial_sig_adapt(
SECP256K1_API int secp256k1_musig_nonce_parity(
const secp256k1_context* ctx,
secp256k1_musig_partial_signature *adaptor_sig,
const secp256k1_musig_partial_signature *partial_sig,
int *nonce_parity,
const secp256k1_musig_session *session
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Creates a signature from a pre-signature and an adaptor.
*
* If the sec_adaptor32 argument is incorrect, the output signature will be
* invalid. This function does not verify the signature.
*
* Returns: 0 if the arguments are invalid, or pre_sig64 or sec_adaptor32 contain
* invalid (overflowing) values. 1 otherwise (which does NOT mean the
* signature or the adaptor are valid!)
* Args: ctx: pointer to a context object
* Out: sig64: 64-byte signature. This pointer may point to the same
* memory area as `pre_sig`.
* In: pre_sig64: 64-byte pre-signature
* sec_adaptor32: 32-byte secret adaptor to add to the pre-signature
* nonce_parity: the output of `musig_nonce_parity` called with the
* session used for producing the pre-signature
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_adapt(
const secp256k1_context* ctx,
unsigned char *sig64,
const unsigned char *pre_sig64,
const unsigned char *sec_adaptor32,
int nonce_parity
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Extracts a secret adaptor from a MuSig, given all parties' partial
* signatures. This function will not fail unless given grossly invalid data; if it
* is merely given signatures that do not verify, the returned value will be
* nonsense. It is therefore important that all data be verified at earlier steps of
* any protocol that uses this function.
/** Extracts a secret adaptor from a MuSig pre-signature and corresponding
* signature
*
* Returns: 1: signatures contained valid data such that an adaptor could be extracted
* 0: otherwise
* Args: ctx: pointer to a context object (cannot be NULL)
* Out:sec_adaptor32: 32-byte secret adaptor (cannot be NULL)
* In: sig64: complete 2-of-2 signature (cannot be NULL)
* partial_sigs: array of partial signatures (cannot be NULL)
* n_partial_sigs: number of elements in partial_sigs array
* nonce_parity: the `nonce_parity` output of `musig_session_combine_nonces`
* This function will not fail unless given grossly invalid data; if it is
* merely given signatures that do not verify, the returned value will be
* nonsense. It is therefore important that all data be verified at earlier
* steps of any protocol that uses this function. In particular, this includes
* verifying all partial signatures that were aggregated into pre_sig64.
*
* Returns: 0 if the arguments are NULL, or sig64 or pre_sig64 contain
* grossly invalid (overflowing) values. 1 otherwise (which does NOT
* mean the signatures or the adaptor are valid!)
* Args: ctx: pointer to a context object
* Out:sec_adaptor32: 32-byte secret adaptor
* In: sig64: complete, valid 64-byte signature
* pre_sig64: the pre-signature corresponding to sig64, i.e., the
* aggregate of partial signatures without the secret
* adaptor
* nonce_parity: the output of `musig_nonce_parity` called with the
* session used for producing sig64
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_secret_adaptor(
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_adaptor(
const secp256k1_context* ctx,
unsigned char *sec_adaptor32,
const unsigned char *sig64,
const secp256k1_musig_partial_signature *partial_sigs,
size_t n_partial_sigs,
const unsigned char *pre_sig64,
int nonce_parity
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

View File

@ -1,16 +1,8 @@
include_HEADERS += include/secp256k1_musig.h
noinst_HEADERS += src/modules/musig/main_impl.h
noinst_HEADERS += src/modules/musig/keyagg.h
noinst_HEADERS += src/modules/musig/keyagg_impl.h
noinst_HEADERS += src/modules/musig/session.h
noinst_HEADERS += src/modules/musig/session_impl.h
noinst_HEADERS += src/modules/musig/adaptor_impl.h
noinst_HEADERS += src/modules/musig/tests_impl.h
noinst_PROGRAMS += example_musig
example_musig_SOURCES = src/modules/musig/example.c
example_musig_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include $(SECP_INCLUDES)
if !ENABLE_COVERAGE
example_musig_CPPFLAGS += -DVERIFY
endif
example_musig_LDADD = libsecp256k1.la $(SECP_LIBS)
example_musig_LDFLAGS = -static
if USE_TESTS
TESTS += example_musig
endif

View File

@ -0,0 +1,101 @@
/***********************************************************************
* Copyright (c) 2021 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_MUSIG_ADAPTOR_IMPL_H
#define SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H
#include <string.h>
#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_musig.h"
#include "session.h"
#include "../../scalar.h"
int secp256k1_musig_nonce_parity(const secp256k1_context* ctx, int *nonce_parity, const secp256k1_musig_session *session) {
secp256k1_musig_session_internal session_i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(nonce_parity != NULL);
ARG_CHECK(session != NULL);
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
return 0;
}
*nonce_parity = session_i.fin_nonce_parity;
return 1;
}
int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *pre_sig64, const unsigned char *sec_adaptor32, int nonce_parity) {
secp256k1_scalar s;
secp256k1_scalar t;
int overflow;
int ret = 1;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig64 != NULL);
ARG_CHECK(pre_sig64 != NULL);
ARG_CHECK(sec_adaptor32 != NULL);
ARG_CHECK(nonce_parity == 0 || nonce_parity == 1);
secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow);
ret &= !overflow;
/* Determine if the secret adaptor should be negated.
*
* The musig_session stores the X-coordinate and the parity of the "final nonce"
* (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor.
*
* Since a BIP340 signature requires an x-only public nonce, in the case where
* (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce
* corresponding to the signature is actually (-r - t)*G. Thus adapting a
* pre-signature requires negating t in this case.
*/
if (nonce_parity) {
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_add(&s, &s, &t);
secp256k1_scalar_get_b32(&sig64[32], &s);
memmove(sig64, pre_sig64, 32);
secp256k1_scalar_clear(&t);
return ret;
}
int secp256k1_musig_extract_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const unsigned char *pre_sig64, int nonce_parity) {
secp256k1_scalar t;
secp256k1_scalar s;
int overflow;
int ret = 1;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sec_adaptor32 != NULL);
ARG_CHECK(sig64 != NULL);
ARG_CHECK(pre_sig64 != NULL);
ARG_CHECK(nonce_parity == 0 || nonce_parity == 1);
secp256k1_scalar_set_b32(&t, &sig64[32], &overflow);
ret &= !overflow;
secp256k1_scalar_negate(&t, &t);
secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_add(&t, &t, &s);
if (!nonce_parity) {
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_get_b32(sec_adaptor32, &t);
secp256k1_scalar_clear(&t);
return ret;
}
#endif

View File

@ -1,170 +0,0 @@
/**********************************************************************
* Copyright (c) 2018 Jonas Nick *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
/**
* This file demonstrates how to use the MuSig module to create a multisignature.
* Additionally, see the documentation in include/secp256k1_musig.h.
*/
#include <stdio.h>
#include <assert.h>
#include <secp256k1.h>
#include <secp256k1_schnorrsig.h>
#include <secp256k1_musig.h>
/* Number of public keys involved in creating the aggregate signature */
#define N_SIGNERS 3
/* Create a key pair and store it in seckey and pubkey */
int create_keypair(const secp256k1_context* ctx, unsigned char *seckey, secp256k1_xonly_pubkey *pubkey) {
int ret;
secp256k1_keypair keypair;
FILE *frand = fopen("/dev/urandom", "r");
if (frand == NULL) {
return 0;
}
do {
if(!fread(seckey, 32, 1, frand)) {
fclose(frand);
return 0;
}
/* The probability that this not a valid secret key is approximately 2^-128 */
} while (!secp256k1_ec_seckey_verify(ctx, seckey));
fclose(frand);
ret = secp256k1_keypair_create(ctx, &keypair, seckey);
ret &= secp256k1_keypair_xonly_pub(ctx, pubkey, NULL, &keypair);
return ret;
}
/* Sign a message hash with the given key pairs and store the result in sig */
int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp256k1_xonly_pubkey** pubkeys, const unsigned char* msg32, unsigned char *sig64) {
secp256k1_musig_session musig_session[N_SIGNERS];
unsigned char nonce_commitment[N_SIGNERS][32];
const unsigned char *nonce_commitment_ptr[N_SIGNERS];
secp256k1_musig_session_signer_data signer_data[N_SIGNERS][N_SIGNERS];
unsigned char nonce[N_SIGNERS][32];
int i, j;
secp256k1_musig_partial_signature partial_sig[N_SIGNERS];
for (i = 0; i < N_SIGNERS; i++) {
FILE *frand;
unsigned char session_id32[32];
secp256k1_xonly_pubkey combined_pk;
secp256k1_musig_pre_session pre_session;
/* Create combined pubkey and initialize signer data */
if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, &pre_session, pubkeys, N_SIGNERS)) {
return 0;
}
/* Create random session ID. It is absolutely necessary that the session ID
* is unique for every call of secp256k1_musig_session_init. Otherwise
* it's trivial for an attacker to extract the secret key! */
frand = fopen("/dev/urandom", "r");
if(frand == NULL) {
return 0;
}
if (!fread(session_id32, 32, 1, frand)) {
fclose(frand);
return 0;
}
fclose(frand);
/* Initialize session */
if (!secp256k1_musig_session_init(ctx, &musig_session[i], signer_data[i], nonce_commitment[i], session_id32, msg32, &combined_pk, &pre_session, N_SIGNERS, seckeys[i])) {
return 0;
}
nonce_commitment_ptr[i] = &nonce_commitment[i][0];
}
/* Communication round 1: Exchange nonce commitments */
for (i = 0; i < N_SIGNERS; i++) {
/* Set nonce commitments in the signer data and get the own public nonce */
if (!secp256k1_musig_session_get_public_nonce(ctx, &musig_session[i], signer_data[i], nonce[i], nonce_commitment_ptr, N_SIGNERS, NULL)) {
return 0;
}
}
/* Communication round 2: Exchange nonces */
for (i = 0; i < N_SIGNERS; i++) {
for (j = 0; j < N_SIGNERS; j++) {
if (!secp256k1_musig_set_nonce(ctx, &signer_data[i][j], nonce[j])) {
/* Signer j's nonce does not match the nonce commitment. In this case
* abort the protocol. If you make another attempt at finishing the
* protocol, create a new session (with a fresh session ID!). */
return 0;
}
}
if (!secp256k1_musig_session_combine_nonces(ctx, &musig_session[i], signer_data[i], N_SIGNERS, NULL, NULL)) {
return 0;
}
}
for (i = 0; i < N_SIGNERS; i++) {
if (!secp256k1_musig_partial_sign(ctx, &musig_session[i], &partial_sig[i])) {
return 0;
}
}
/* Communication round 3: Exchange partial signatures */
for (i = 0; i < N_SIGNERS; i++) {
for (j = 0; j < N_SIGNERS; j++) {
/* To check whether signing was successful, it suffices to either verify
* the combined signature with the combined public key using
* secp256k1_schnorrsig_verify, or verify all partial signatures of all
* signers individually. Verifying the combined 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 combined
* signature to be invalid and thus the protocol run to fail. It's also
* fine to first verify the combined sig, and only verify the individual
* sigs if it does not work.
*/
if (!secp256k1_musig_partial_sig_verify(ctx, &musig_session[i], &signer_data[i][j], &partial_sig[j], pubkeys[j])) {
return 0;
}
}
}
return secp256k1_musig_partial_sig_combine(ctx, &musig_session[0], sig64, partial_sig, N_SIGNERS);
}
int main(void) {
secp256k1_context* ctx;
int i;
unsigned char seckeys[N_SIGNERS][32];
secp256k1_xonly_pubkey pubkeys[N_SIGNERS];
const secp256k1_xonly_pubkey *pubkeys_ptr[N_SIGNERS];
secp256k1_xonly_pubkey combined_pk;
unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!";
unsigned char sig[64];
/* Create a context for signing and verification */
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
printf("Creating key pairs......");
for (i = 0; i < N_SIGNERS; i++) {
if (!create_keypair(ctx, seckeys[i], &pubkeys[i])) {
printf("FAILED\n");
return 1;
}
pubkeys_ptr[i] = &pubkeys[i];
}
printf("ok\n");
printf("Combining public keys...");
if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, NULL, pubkeys_ptr, N_SIGNERS)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
printf("Signing message.........");
if (!sign(ctx, seckeys, pubkeys_ptr, msg, sig)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
printf("Verifying signature.....");
if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &combined_pk)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
secp256k1_context_destroy(ctx);
return 0;
}

View File

@ -0,0 +1,34 @@
/***********************************************************************
* Copyright (c) 2021 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_MUSIG_KEYAGG_H
#define SECP256K1_MODULE_MUSIG_KEYAGG_H
#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_musig.h"
#include "../../field.h"
#include "../../group.h"
#include "../../scalar.h"
typedef struct {
secp256k1_ge pk;
secp256k1_fe second_pk_x;
unsigned char pk_hash[32];
secp256k1_scalar tweak;
int internal_key_parity;
} secp256k1_keyagg_cache_internal;
/* Requires that the saved point is not infinity */
static void secp256k1_point_save(unsigned char *data, secp256k1_ge *ge);
static void secp256k1_point_load(secp256k1_ge *ge, const unsigned char *data);
static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache);
static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_fe *x);
#endif

View File

@ -0,0 +1,280 @@
/***********************************************************************
* Copyright (c) 2021 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_MUSIG_KEYAGG_IMPL_H
#define SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H
#include <string.h>
#include "keyagg.h"
#include "../../eckey.h"
#include "../../ecmult.h"
#include "../../field.h"
#include "../../group.h"
#include "../../hash.h"
#include "../../util.h"
static void secp256k1_point_save(unsigned char *data, secp256k1_ge *ge) {
if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge);
memcpy(data, &s, sizeof(s));
} else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(data, &ge->x);
secp256k1_fe_get_b32(data + 32, &ge->y);
}
}
static void secp256k1_point_load(secp256k1_ge *ge, const unsigned char *data) {
if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation as conversion is very fast. */
secp256k1_ge_storage s;
memcpy(&s, data, sizeof(s));
secp256k1_ge_from_storage(ge, &s);
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
secp256k1_fe_set_b32(&x, data);
secp256k1_fe_set_b32(&y, data + 32);
secp256k1_ge_set_xy(ge, &x, &y);
}
}
static const unsigned char secp256k1_musig_keyagg_cache_magic[4] = { 0xf4, 0xad, 0xbb, 0xdf };
/* A keyagg cache consists of
* - 4 byte magic set during initialization to allow detecting an uninitialized
* object.
* - 64 byte aggregate (and potentially tweaked) public key
* - 32 byte X-coordinate of "second" public key (0 if not present)
* - 32 byte hash of all public keys
* - 1 byte the parity of the internal key (if tweaked, otherwise 0)
* - 32 byte tweak
*/
/* Requires that cache_i->pk is not infinity and cache_i->second_pk_x to be normalized. */
static void secp256k1_keyagg_cache_save(secp256k1_musig_keyagg_cache *cache, secp256k1_keyagg_cache_internal *cache_i) {
unsigned char *ptr = cache->data;
memcpy(ptr, secp256k1_musig_keyagg_cache_magic, 4);
ptr += 4;
secp256k1_point_save(ptr, &cache_i->pk);
ptr += 64;
secp256k1_fe_get_b32(ptr, &cache_i->second_pk_x);
ptr += 32;
memcpy(ptr, cache_i->pk_hash, 32);
ptr += 32;
*ptr = cache_i->internal_key_parity;
ptr += 1;
secp256k1_scalar_get_b32(ptr, &cache_i->tweak);
}
static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache) {
const unsigned char *ptr = cache->data;
ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_keyagg_cache_magic, 4) == 0);
ptr += 4;
secp256k1_point_load(&cache_i->pk, ptr);
ptr += 64;
secp256k1_fe_set_b32(&cache_i->second_pk_x, ptr);
ptr += 32;
memcpy(cache_i->pk_hash, ptr, 32);
ptr += 32;
cache_i->internal_key_parity = *ptr & 1;
ptr += 1;
secp256k1_scalar_set_b32(&cache_i->tweak, ptr, NULL);
return 1;
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */
static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0xb399d5e0ul;
sha->s[1] = 0xc8fff302ul;
sha->s[2] = 0x6badac71ul;
sha->s[3] = 0x07c5b7f1ul;
sha->s[4] = 0x9701e2eful;
sha->s[5] = 0x2a72ecf8ul;
sha->s[6] = 0x201a4c7bul;
sha->s[7] = 0xab148a38ul;
sha->bytes = 64;
}
/* Computes pk_hash = tagged_hash(pk[0], ..., pk[np-1]) */
static int secp256k1_musig_compute_pk_hash(const secp256k1_context *ctx, unsigned char *pk_hash, const secp256k1_xonly_pubkey * const* pk, size_t np) {
secp256k1_sha256 sha;
size_t i;
secp256k1_musig_keyagglist_sha256(&sha);
for (i = 0; i < np; i++) {
unsigned char ser[32];
if (!secp256k1_xonly_pubkey_serialize(ctx, ser, pk[i])) {
return 0;
}
secp256k1_sha256_write(&sha, ser, 32);
}
secp256k1_sha256_finalize(&sha, pk_hash);
return 1;
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */
static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0x6ef02c5aul;
sha->s[1] = 0x06a480deul;
sha->s[2] = 0x1f298665ul;
sha->s[3] = 0x1d1134f2ul;
sha->s[4] = 0x56a0b063ul;
sha->s[5] = 0x52da4147ul;
sha->s[6] = 0xf280d9d4ul;
sha->s[7] = 0x4484be15ul;
sha->bytes = 64;
}
/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and
* tagged_hash(pk_hash, x) where pk_hash is the hash of public keys otherwise.
* second_pk_x can be 0 in case there is no second_pk. Assumes both field
* elements x and second_pk_x are normalized. */
static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pk_hash, const secp256k1_fe *x, const secp256k1_fe *second_pk_x) {
secp256k1_sha256 sha;
unsigned char buf[32];
if (secp256k1_fe_cmp_var(x, second_pk_x) == 0) {
secp256k1_scalar_set_int(r, 1);
} else {
secp256k1_musig_keyaggcoef_sha256(&sha);
secp256k1_sha256_write(&sha, pk_hash, 32);
secp256k1_fe_get_b32(buf, x);
secp256k1_sha256_write(&sha, buf, 32);
secp256k1_sha256_finalize(&sha, buf);
secp256k1_scalar_set_b32(r, buf, NULL);
}
}
/* Assumes both field elements x and second_pk_x are normalized. */
static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_fe *x) {
secp256k1_musig_keyaggcoef_internal(r, cache_i->pk_hash, x, &cache_i->second_pk_x);
}
typedef struct {
const secp256k1_context *ctx;
/* pk_hash is the hash of the public keys */
unsigned char pk_hash[32];
const secp256k1_xonly_pubkey * const* pks;
secp256k1_fe second_pk_x;
} secp256k1_musig_pubkey_agg_ecmult_data;
/* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ... */
static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) {
secp256k1_musig_pubkey_agg_ecmult_data *ctx = (secp256k1_musig_pubkey_agg_ecmult_data *) data;
int ret;
ret = secp256k1_xonly_pubkey_load(ctx->ctx, pt, ctx->pks[idx]);
/* pubkey_load can't fail because the same pks have already been loaded in
* `musig_compute_pk_hash` (and we test this). */
VERIFY_CHECK(ret);
secp256k1_musig_keyaggcoef_internal(sc, ctx->pk_hash, &pt->x, &ctx->second_pk_x);
return 1;
}
int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_xonly_pubkey * const* pubkeys, size_t n_pubkeys) {
secp256k1_musig_pubkey_agg_ecmult_data ecmult_data;
secp256k1_gej pkj;
secp256k1_ge pkp;
size_t i;
VERIFY_CHECK(ctx != NULL);
if (agg_pk != NULL) {
memset(agg_pk, 0, sizeof(*agg_pk));
}
ARG_CHECK(pubkeys != NULL);
ARG_CHECK(n_pubkeys > 0);
ecmult_data.ctx = ctx;
ecmult_data.pks = pubkeys;
/* No point on the curve has an X coordinate equal to 0 */
secp256k1_fe_set_int(&ecmult_data.second_pk_x, 0);
for (i = 1; i < n_pubkeys; i++) {
if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) {
secp256k1_ge pt;
if (!secp256k1_xonly_pubkey_load(ctx, &pt, pubkeys[i])) {
return 0;
}
ecmult_data.second_pk_x = pt.x;
break;
}
}
if (!secp256k1_musig_compute_pk_hash(ctx, ecmult_data.pk_hash, pubkeys, n_pubkeys)) {
return 0;
}
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &pkj, NULL, secp256k1_musig_pubkey_agg_callback, (void *) &ecmult_data, n_pubkeys)) {
/* In order to reach this line with the current implementation of
* ecmult_multi_var one would need to provide a callback that can
* fail. */
return 0;
}
secp256k1_ge_set_gej(&pkp, &pkj);
secp256k1_fe_normalize_var(&pkp.y);
/* The resulting public key is infinity with negligible probability */
VERIFY_CHECK(!secp256k1_ge_is_infinity(&pkp));
if (keyagg_cache != NULL) {
secp256k1_keyagg_cache_internal cache_i = { 0 };
cache_i.pk = pkp;
cache_i.second_pk_x = ecmult_data.second_pk_x;
memcpy(cache_i.pk_hash, ecmult_data.pk_hash, sizeof(cache_i.pk_hash));
secp256k1_keyagg_cache_save(keyagg_cache, &cache_i);
}
secp256k1_extrakeys_ge_even_y(&pkp);
if (agg_pk != NULL) {
secp256k1_xonly_pubkey_save(agg_pk, &pkp);
}
return 1;
}
int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
secp256k1_keyagg_cache_internal cache_i;
int overflow = 0;
secp256k1_scalar tweak;
VERIFY_CHECK(ctx != NULL);
if (output_pubkey != NULL) {
memset(output_pubkey, 0, sizeof(*output_pubkey));
}
ARG_CHECK(keyagg_cache != NULL);
ARG_CHECK(tweak32 != NULL);
if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
return 0;
}
secp256k1_scalar_set_b32(&tweak, tweak32, &overflow);
if (overflow) {
return 0;
}
if (secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
cache_i.internal_key_parity ^= 1;
secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak);
}
secp256k1_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak);
if (!secp256k1_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) {
return 0;
}
/* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */
VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk));
secp256k1_keyagg_cache_save(keyagg_cache, &cache_i);
if (output_pubkey != NULL) {
secp256k1_pubkey_save(output_pubkey, &cache_i.pk);
}
return 1;
}
#endif

View File

@ -4,735 +4,11 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_MODULE_MUSIG_MAIN_
#define _SECP256K1_MODULE_MUSIG_MAIN_
#ifndef SECP256K1_MODULE_MUSIG_MAIN
#define SECP256K1_MODULE_MUSIG_MAIN
#include <stdint.h>
#include "include/secp256k1.h"
#include "include/secp256k1_musig.h"
#include "hash.h"
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */
static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0xb399d5e0ul;
sha->s[1] = 0xc8fff302ul;
sha->s[2] = 0x6badac71ul;
sha->s[3] = 0x07c5b7f1ul;
sha->s[4] = 0x9701e2eful;
sha->s[5] = 0x2a72ecf8ul;
sha->s[6] = 0x201a4c7bul;
sha->s[7] = 0xab148a38ul;
sha->bytes = 64;
}
/* Computes ell = SHA256(pk[0], ..., pk[np-1]) */
static int secp256k1_musig_compute_ell(const secp256k1_context *ctx, unsigned char *ell, const secp256k1_xonly_pubkey * const* pk, size_t np) {
secp256k1_sha256 sha;
size_t i;
secp256k1_musig_keyagglist_sha256(&sha);
for (i = 0; i < np; i++) {
unsigned char ser[32];
if (!secp256k1_xonly_pubkey_serialize(ctx, ser, pk[i])) {
return 0;
}
secp256k1_sha256_write(&sha, ser, 32);
}
secp256k1_sha256_finalize(&sha, ell);
return 1;
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */
static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0x6ef02c5aul;
sha->s[1] = 0x06a480deul;
sha->s[2] = 0x1f298665ul;
sha->s[3] = 0x1d1134f2ul;
sha->s[4] = 0x56a0b063ul;
sha->s[5] = 0x52da4147ul;
sha->s[6] = 0xf280d9d4ul;
sha->s[7] = 0x4484be15ul;
sha->bytes = 64;
}
/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and
* SHA256(ell, x) otherwise. second_pk_x can be NULL in case there is no
* second_pk. Assumes both field elements x and second_pk_x are normalized. */
static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *ell, secp256k1_fe *x, const secp256k1_fe *second_pk_x) {
secp256k1_sha256 sha;
unsigned char buf[32];
if (secp256k1_fe_cmp_var(x, second_pk_x) == 0) {
secp256k1_scalar_set_int(r, 1);
} else {
secp256k1_musig_keyaggcoef_sha256(&sha);
secp256k1_sha256_write(&sha, ell, 32);
secp256k1_fe_get_b32(buf, x);
secp256k1_sha256_write(&sha, buf, 32);
secp256k1_sha256_finalize(&sha, buf);
secp256k1_scalar_set_b32(r, buf, NULL);
}
}
/* Assumes both field elements x and second_pk_x are normalized. */
static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_musig_pre_session *pre_session, secp256k1_fe *x) {
secp256k1_fe second_pk_x;
secp256k1_fe_set_b32(&second_pk_x, pre_session->second_pk);
secp256k1_musig_keyaggcoef_internal(r, pre_session->pk_hash, x, &second_pk_x);
}
typedef struct {
const secp256k1_context *ctx;
unsigned char ell[32];
const secp256k1_xonly_pubkey * const* pks;
secp256k1_fe second_pk_x;
} secp256k1_musig_pubkey_combine_ecmult_data;
/* Callback for batch EC multiplication to compute ell_0*P0 + ell_1*P1 + ... */
static int secp256k1_musig_pubkey_combine_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) {
secp256k1_musig_pubkey_combine_ecmult_data *ctx = (secp256k1_musig_pubkey_combine_ecmult_data *) data;
int ret;
ret = secp256k1_xonly_pubkey_load(ctx->ctx, pt, ctx->pks[idx]);
/* pubkey_load can't fail because the same pks have already been loaded (and
* we test this) */
VERIFY_CHECK(ret);
secp256k1_musig_keyaggcoef_internal(sc, ctx->ell, &pt->x, &ctx->second_pk_x);
return 1;
}
static void secp256k1_musig_signers_init(secp256k1_musig_session_signer_data *signers, uint32_t n_signers) {
uint32_t i;
for (i = 0; i < n_signers; i++) {
memset(&signers[i], 0, sizeof(signers[i]));
signers[i].present = 0;
}
}
static const uint64_t pre_session_magic = 0xf4adbbdf7c7dd304UL;
int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_xonly_pubkey *combined_pk, secp256k1_musig_pre_session *pre_session, const secp256k1_xonly_pubkey * const* pubkeys, size_t n_pubkeys) {
secp256k1_musig_pubkey_combine_ecmult_data ecmult_data;
secp256k1_gej pkj;
secp256k1_ge pkp;
int pk_parity;
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(combined_pk != NULL);
ARG_CHECK(pubkeys != NULL);
ARG_CHECK(n_pubkeys > 0);
ecmult_data.ctx = ctx;
ecmult_data.pks = pubkeys;
/* No point on the curve has an X coordinate equal to 0 */
secp256k1_fe_set_int(&ecmult_data.second_pk_x, 0);
for (i = 1; i < n_pubkeys; i++) {
secp256k1_ge pt;
if (!secp256k1_xonly_pubkey_load(ctx, &pt, pubkeys[i])) {
return 0;
}
if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) {
ecmult_data.second_pk_x = pt.x;
break;
}
}
if (!secp256k1_musig_compute_ell(ctx, ecmult_data.ell, pubkeys, n_pubkeys)) {
return 0;
}
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &pkj, NULL, secp256k1_musig_pubkey_combine_callback, (void *) &ecmult_data, n_pubkeys)) {
/* The current implementation of ecmult_multi_var makes this code unreachable with tests. */
return 0;
}
secp256k1_ge_set_gej(&pkp, &pkj);
secp256k1_fe_normalize_var(&pkp.y);
pk_parity = secp256k1_extrakeys_ge_even_y(&pkp);
secp256k1_xonly_pubkey_save(combined_pk, &pkp);
if (pre_session != NULL) {
pre_session->magic = pre_session_magic;
memcpy(pre_session->pk_hash, ecmult_data.ell, 32);
pre_session->pk_parity = pk_parity;
pre_session->is_tweaked = 0;
secp256k1_fe_get_b32(pre_session->second_pk, &ecmult_data.second_pk_x);
}
return 1;
}
int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_musig_pre_session *pre_session, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
secp256k1_ge pk;
int ret;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(pre_session != NULL);
ARG_CHECK(pre_session->magic == pre_session_magic);
/* This function can only be called once because otherwise signing would not
* succeed */
ARG_CHECK(pre_session->is_tweaked == 0);
pre_session->internal_key_parity = pre_session->pk_parity;
if(!secp256k1_xonly_pubkey_tweak_add(ctx, output_pubkey, internal_pubkey, tweak32)) {
return 0;
}
memcpy(pre_session->tweak, tweak32, 32);
pre_session->is_tweaked = 1;
ret = secp256k1_pubkey_load(ctx, &pk, output_pubkey);
/* Successful xonly_pubkey_tweak_add always returns valid output_pubkey */
VERIFY_CHECK(ret);
pre_session->pk_parity = secp256k1_extrakeys_ge_even_y(&pk);
return 1;
}
static const uint64_t session_magic = 0xd92e6fc1ee41b4cbUL;
int secp256k1_musig_session_init(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, unsigned char *nonce_commitment32, const unsigned char *session_id32, const unsigned char *msg32, const secp256k1_xonly_pubkey *combined_pk, const secp256k1_musig_pre_session *pre_session, size_t n_signers, const unsigned char *seckey) {
unsigned char combined_ser[32];
int overflow;
secp256k1_scalar secret;
secp256k1_scalar mu;
secp256k1_sha256 sha;
secp256k1_gej pj;
secp256k1_ge p;
unsigned char nonce_ser[32];
size_t nonce_ser_size = sizeof(nonce_ser);
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(session != NULL);
ARG_CHECK(signers != NULL);
ARG_CHECK(nonce_commitment32 != NULL);
ARG_CHECK(session_id32 != NULL);
ARG_CHECK(combined_pk != NULL);
ARG_CHECK(pre_session != NULL);
ARG_CHECK(pre_session->magic == pre_session_magic);
ARG_CHECK(seckey != NULL);
ARG_CHECK(n_signers > 0);
ARG_CHECK(n_signers <= UINT32_MAX);
memset(session, 0, sizeof(*session));
session->magic = session_magic;
if (msg32 != NULL) {
memcpy(session->msg, msg32, 32);
session->is_msg_set = 1;
} else {
session->is_msg_set = 0;
}
memcpy(&session->combined_pk, combined_pk, sizeof(*combined_pk));
session->pre_session = *pre_session;
session->has_secret_data = 1;
session->n_signers = (uint32_t) n_signers;
secp256k1_musig_signers_init(signers, session->n_signers);
/* Compute secret key */
secp256k1_scalar_set_b32(&secret, seckey, &overflow);
if (overflow) {
secp256k1_scalar_clear(&secret);
return 0;
}
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &secret);
secp256k1_ge_set_gej(&p, &pj);
secp256k1_fe_normalize_var(&p.x);
secp256k1_musig_keyaggcoef(&mu, &session->pre_session, &p.x);
/* Compute the signer's public key point and determine if the secret is
* negated before signing. That happens if if the signer's pubkey has an odd
* Y coordinate XOR the MuSig-combined pubkey has an odd Y coordinate XOR
* (if tweaked) the internal key has an odd Y coordinate.
*
* This can be seen by looking at the secret key belonging to `combined_pk`.
* Let's define
* P' := mu_0*|P_0| + ... + mu_n*|P_n| where P_i is the i-th public key
* point x_i*G, mu_i is the i-th KeyAgg coefficient and |.| is a function
* that normalizes a point to an even Y by negating if necessary similar to
* secp256k1_extrakeys_ge_even_y. Then we have
* P := |P'| + t*G where t is the tweak.
* And the combined xonly public key is
* |P| = x*G
* where x = sum_i(b_i*mu_i*x_i) + b'*t
* b' = -1 if P != |P|, 1 otherwise
* b_i = -1 if (P_i != |P_i| XOR P' != |P'| XOR P != |P|) and 1
* otherwise.
*/
secp256k1_fe_normalize_var(&p.y);
if((secp256k1_fe_is_odd(&p.y)
+ session->pre_session.pk_parity
+ (session->pre_session.is_tweaked
&& session->pre_session.internal_key_parity))
% 2 == 1) {
secp256k1_scalar_negate(&secret, &secret);
}
secp256k1_scalar_mul(&secret, &secret, &mu);
secp256k1_scalar_get_b32(session->seckey, &secret);
/* Compute secret nonce */
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, session_id32, 32);
if (session->is_msg_set) {
secp256k1_sha256_write(&sha, msg32, 32);
}
secp256k1_xonly_pubkey_serialize(ctx, combined_ser, combined_pk);
secp256k1_sha256_write(&sha, combined_ser, 32);
secp256k1_sha256_write(&sha, seckey, 32);
secp256k1_sha256_finalize(&sha, session->secnonce);
secp256k1_scalar_set_b32(&secret, session->secnonce, &overflow);
if (overflow) {
secp256k1_scalar_clear(&secret);
return 0;
}
/* Compute public nonce and commitment */
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &secret);
secp256k1_ge_set_gej(&p, &pj);
secp256k1_fe_normalize_var(&p.y);
session->partial_nonce_parity = secp256k1_extrakeys_ge_even_y(&p);
secp256k1_xonly_pubkey_save(&session->nonce, &p);
secp256k1_sha256_initialize(&sha);
secp256k1_xonly_pubkey_serialize(ctx, nonce_ser, &session->nonce);
secp256k1_sha256_write(&sha, nonce_ser, nonce_ser_size);
secp256k1_sha256_finalize(&sha, nonce_commitment32);
session->round = 0;
secp256k1_scalar_clear(&secret);
return 1;
}
int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, unsigned char *nonce, const unsigned char *const *commitments, size_t n_commitments, const unsigned char *msg32) {
secp256k1_sha256 sha;
unsigned char nonce_commitments_hash[32];
size_t i;
unsigned char nonce_ser[32];
size_t nonce_ser_size = sizeof(nonce_ser);
(void) ctx;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(session->magic == session_magic);
ARG_CHECK(signers != NULL);
ARG_CHECK(nonce != NULL);
ARG_CHECK(commitments != NULL);
ARG_CHECK(session->round == 0);
/* If the message was not set during initialization it must be set now. */
ARG_CHECK(!(!session->is_msg_set && msg32 == NULL));
/* The message can only be set once. */
ARG_CHECK(!(session->is_msg_set && msg32 != NULL));
ARG_CHECK(session->has_secret_data);
ARG_CHECK(n_commitments == session->n_signers);
for (i = 0; i < n_commitments; i++) {
ARG_CHECK(commitments[i] != NULL);
}
if (msg32 != NULL) {
memcpy(session->msg, msg32, 32);
session->is_msg_set = 1;
}
secp256k1_sha256_initialize(&sha);
for (i = 0; i < n_commitments; i++) {
memcpy(signers[i].nonce_commitment, commitments[i], 32);
secp256k1_sha256_write(&sha, commitments[i], 32);
}
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
memcpy(session->nonce_commitments_hash, nonce_commitments_hash, 32);
secp256k1_xonly_pubkey_serialize(ctx, nonce_ser, &session->nonce);
memcpy(nonce, &nonce_ser, nonce_ser_size);
session->round = 1;
return 1;
}
int secp256k1_musig_session_init_verifier(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, const unsigned char *msg32, const secp256k1_xonly_pubkey *combined_pk, const secp256k1_musig_pre_session *pre_session, const unsigned char *const *commitments, size_t n_signers) {
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(signers != NULL);
ARG_CHECK(msg32 != NULL);
ARG_CHECK(combined_pk != NULL);
ARG_CHECK(pre_session != NULL);
ARG_CHECK(pre_session->magic == pre_session_magic);
ARG_CHECK(commitments != NULL);
/* Check n_signers before checking commitments to allow testing the case where
* n_signers is big without allocating the space. */
ARG_CHECK(n_signers > 0);
ARG_CHECK(n_signers <= UINT32_MAX);
for (i = 0; i < n_signers; i++) {
ARG_CHECK(commitments[i] != NULL);
}
(void) ctx;
memset(session, 0, sizeof(*session));
session->magic = session_magic;
memcpy(&session->combined_pk, combined_pk, sizeof(*combined_pk));
session->pre_session = *pre_session;
session->n_signers = (uint32_t) n_signers;
secp256k1_musig_signers_init(signers, session->n_signers);
session->pre_session = *pre_session;
session->is_msg_set = 1;
memcpy(session->msg, msg32, 32);
session->has_secret_data = 0;
for (i = 0; i < n_signers; i++) {
memcpy(signers[i].nonce_commitment, commitments[i], 32);
}
session->round = 1;
return 1;
}
int secp256k1_musig_set_nonce(const secp256k1_context* ctx, secp256k1_musig_session_signer_data *signer, const unsigned char *nonce) {
secp256k1_sha256 sha;
unsigned char commit[32];
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(signer != NULL);
ARG_CHECK(nonce != NULL);
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, nonce, 32);
secp256k1_sha256_finalize(&sha, commit);
if (memcmp(commit, signer->nonce_commitment, 32) != 0) {
return 0;
}
memcpy(&signer->nonce, nonce, sizeof(*nonce));
if (!secp256k1_xonly_pubkey_parse(ctx, &signer->nonce, nonce)) {
return 0;
}
signer->present = 1;
return 1;
}
int secp256k1_musig_session_combine_nonces(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_session_signer_data *signers, size_t n_signers, int *nonce_parity, const secp256k1_pubkey *adaptor) {
secp256k1_gej combined_noncej;
secp256k1_ge combined_noncep;
secp256k1_ge noncep;
secp256k1_sha256 sha;
unsigned char nonce_commitments_hash[32];
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(signers != NULL);
ARG_CHECK(session->magic == session_magic);
ARG_CHECK(session->round == 1);
ARG_CHECK(n_signers == session->n_signers);
secp256k1_sha256_initialize(&sha);
secp256k1_gej_set_infinity(&combined_noncej);
for (i = 0; i < n_signers; i++) {
if (!signers[i].present) {
return 0;
}
secp256k1_sha256_write(&sha, signers[i].nonce_commitment, 32);
secp256k1_xonly_pubkey_load(ctx, &noncep, &signers[i].nonce);
secp256k1_gej_add_ge_var(&combined_noncej, &combined_noncej, &noncep, NULL);
}
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
/* If the signers' commitments changed between get_public_nonce and now we
* have to abort because in that case they may have seen our nonce before
* creating their commitment. That can happen if the signer_data given to
* this function is different to the signer_data given to get_public_nonce.
* */
if (session->has_secret_data
&& memcmp(session->nonce_commitments_hash, nonce_commitments_hash, 32) != 0) {
return 0;
}
/* Add public adaptor to nonce */
if (adaptor != NULL) {
secp256k1_pubkey_load(ctx, &noncep, adaptor);
secp256k1_gej_add_ge_var(&combined_noncej, &combined_noncej, &noncep, NULL);
}
/* Negate nonce if Y coordinate is not square */
secp256k1_ge_set_gej(&combined_noncep, &combined_noncej);
secp256k1_fe_normalize_var(&combined_noncep.y);
session->combined_nonce_parity = secp256k1_extrakeys_ge_even_y(&combined_noncep);
if (nonce_parity != NULL) {
*nonce_parity = session->combined_nonce_parity;
}
secp256k1_xonly_pubkey_save(&session->combined_nonce, &combined_noncep);
session->round = 2;
return 1;
}
int secp256k1_musig_partial_signature_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_signature* sig) {
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(out32 != NULL);
ARG_CHECK(sig != NULL);
memcpy(out32, sig->data, 32);
return 1;
}
int secp256k1_musig_partial_signature_parse(const secp256k1_context* ctx, secp256k1_musig_partial_signature* sig, const unsigned char *in32) {
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig != NULL);
ARG_CHECK(in32 != NULL);
memcpy(sig->data, in32, 32);
return 1;
}
/* Compute msghash = SHA256(combined_nonce, combined_pk, msg) */
static void secp256k1_musig_compute_messagehash(const secp256k1_context *ctx, unsigned char *msghash, const secp256k1_musig_session *session) {
unsigned char buf[32];
secp256k1_ge rp;
secp256k1_sha256 sha;
VERIFY_CHECK(session->round >= 2);
secp256k1_schnorrsig_sha256_tagged(&sha);
secp256k1_xonly_pubkey_load(ctx, &rp, &session->combined_nonce);
secp256k1_fe_get_b32(buf, &rp.x);
secp256k1_sha256_write(&sha, buf, 32);
secp256k1_xonly_pubkey_serialize(ctx, buf, &session->combined_pk);
secp256k1_sha256_write(&sha, buf, 32);
secp256k1_sha256_write(&sha, session->msg, 32);
secp256k1_sha256_finalize(&sha, msghash);
}
int secp256k1_musig_partial_sign(const secp256k1_context* ctx, const secp256k1_musig_session *session, secp256k1_musig_partial_signature *partial_sig) {
unsigned char msghash[32];
int overflow;
secp256k1_scalar sk;
secp256k1_scalar e, k;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(partial_sig != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(session->magic == session_magic);
ARG_CHECK(session->round == 2);
ARG_CHECK(session->has_secret_data);
/* build message hash */
secp256k1_musig_compute_messagehash(ctx, msghash, session);
secp256k1_scalar_set_b32(&e, msghash, NULL);
secp256k1_scalar_set_b32(&sk, session->seckey, &overflow);
if (overflow) {
secp256k1_scalar_clear(&sk);
return 0;
}
secp256k1_scalar_set_b32(&k, session->secnonce, &overflow);
if (overflow || secp256k1_scalar_is_zero(&k)) {
secp256k1_scalar_clear(&sk);
secp256k1_scalar_clear(&k);
return 0;
}
if (session->partial_nonce_parity != session->combined_nonce_parity) {
secp256k1_scalar_negate(&k, &k);
}
/* Sign */
secp256k1_scalar_mul(&e, &e, &sk);
secp256k1_scalar_add(&e, &e, &k);
secp256k1_scalar_get_b32(&partial_sig->data[0], &e);
secp256k1_scalar_clear(&sk);
secp256k1_scalar_clear(&k);
return 1;
}
int secp256k1_musig_partial_sig_combine(const secp256k1_context* ctx, const secp256k1_musig_session *session, unsigned char *sig64, const secp256k1_musig_partial_signature *partial_sigs, size_t n_sigs) {
size_t i;
secp256k1_scalar s;
secp256k1_ge noncep;
(void) ctx;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig64 != NULL);
ARG_CHECK(partial_sigs != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(session->magic == session_magic);
ARG_CHECK(session->round == 2);
if (n_sigs != session->n_signers) {
return 0;
}
secp256k1_scalar_clear(&s);
for (i = 0; i < n_sigs; i++) {
int overflow;
secp256k1_scalar term;
secp256k1_scalar_set_b32(&term, partial_sigs[i].data, &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_add(&s, &s, &term);
}
/* If there is a tweak then add (or subtract) `msghash` times `tweak` to `s`.*/
if (session->pre_session.is_tweaked) {
unsigned char msghash[32];
secp256k1_scalar e, scalar_tweak;
int overflow = 0;
secp256k1_musig_compute_messagehash(ctx, msghash, session);
secp256k1_scalar_set_b32(&e, msghash, NULL);
secp256k1_scalar_set_b32(&scalar_tweak, session->pre_session.tweak, &overflow);
if (overflow || !secp256k1_eckey_privkey_tweak_mul(&e, &scalar_tweak)) {
/* This mimics the behavior of secp256k1_ec_seckey_tweak_mul regarding
* overflow and tweak being 0. */
return 0;
}
if (session->pre_session.pk_parity) {
secp256k1_scalar_negate(&e, &e);
}
secp256k1_scalar_add(&s, &s, &e);
}
secp256k1_xonly_pubkey_load(ctx, &noncep, &session->combined_nonce);
VERIFY_CHECK(!secp256k1_fe_is_odd(&noncep.y));
secp256k1_fe_normalize(&noncep.x);
secp256k1_fe_get_b32(&sig64[0], &noncep.x);
secp256k1_scalar_get_b32(&sig64[32], &s);
return 1;
}
int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_musig_session *session, const secp256k1_musig_session_signer_data *signer, const secp256k1_musig_partial_signature *partial_sig, const secp256k1_xonly_pubkey *pubkey) {
unsigned char msghash[32];
secp256k1_scalar s;
secp256k1_scalar e;
secp256k1_scalar mu;
secp256k1_gej pkj;
secp256k1_gej rj;
secp256k1_ge pkp;
secp256k1_ge rp;
int overflow;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(signer != NULL);
ARG_CHECK(partial_sig != NULL);
ARG_CHECK(pubkey != NULL);
ARG_CHECK(session->magic == session_magic);
ARG_CHECK(session->round == 2);
ARG_CHECK(signer->present);
secp256k1_scalar_set_b32(&s, partial_sig->data, &overflow);
if (overflow) {
return 0;
}
secp256k1_musig_compute_messagehash(ctx, msghash, session);
secp256k1_scalar_set_b32(&e, msghash, NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pkp, pubkey)) {
return 0;
}
/* Multiplying the messagehash by the KeyAgg coefficient is equivalent
* to multiplying the signer's public key by the coefficient, except
* much easier to do. */
secp256k1_musig_keyaggcoef(&mu, &session->pre_session, &pkp.x);
secp256k1_scalar_mul(&e, &e, &mu);
if (!secp256k1_xonly_pubkey_load(ctx, &rp, &signer->nonce)) {
return 0;
}
/* If the MuSig-combined point has an odd Y coordinate, the signers will
* sign for the negation of their individual xonly public key such that the
* combined signature is valid for the MuSig aggregated xonly key. If the
* MuSig-combined point was tweaked then `e` is negated if the combined key
* has an odd Y coordinate XOR the internal key has an odd Y coordinate.*/
if (session->pre_session.pk_parity
!= (session->pre_session.is_tweaked
&& session->pre_session.internal_key_parity)) {
secp256k1_scalar_negate(&e, &e);
}
/* Compute rj = s*G + (-e)*pkj */
secp256k1_scalar_negate(&e, &e);
secp256k1_gej_set_ge(&pkj, &pkp);
secp256k1_ecmult(&rj, &pkj, &e, &s);
if (!session->combined_nonce_parity) {
secp256k1_ge_neg(&rp, &rp);
}
secp256k1_gej_add_ge_var(&rj, &rj, &rp, NULL);
return secp256k1_gej_is_infinity(&rj);
}
int secp256k1_musig_partial_sig_adapt(const secp256k1_context* ctx, secp256k1_musig_partial_signature *adaptor_sig, const secp256k1_musig_partial_signature *partial_sig, const unsigned char *sec_adaptor32, int nonce_parity) {
secp256k1_scalar s;
secp256k1_scalar t;
int overflow;
(void) ctx;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(adaptor_sig != NULL);
ARG_CHECK(partial_sig != NULL);
ARG_CHECK(sec_adaptor32 != NULL);
secp256k1_scalar_set_b32(&s, partial_sig->data, &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow);
if (overflow) {
secp256k1_scalar_clear(&t);
return 0;
}
if (nonce_parity) {
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_add(&s, &s, &t);
secp256k1_scalar_get_b32(adaptor_sig->data, &s);
secp256k1_scalar_clear(&t);
return 1;
}
int secp256k1_musig_extract_secret_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const secp256k1_musig_partial_signature *partial_sigs, size_t n_partial_sigs, int nonce_parity) {
secp256k1_scalar t;
secp256k1_scalar s;
int overflow;
size_t i;
(void) ctx;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sec_adaptor32 != NULL);
ARG_CHECK(sig64 != NULL);
ARG_CHECK(partial_sigs != NULL);
secp256k1_scalar_set_b32(&t, &sig64[32], &overflow);
if (overflow) {
return 0;
}
secp256k1_scalar_negate(&t, &t);
for (i = 0; i < n_partial_sigs; i++) {
secp256k1_scalar_set_b32(&s, partial_sigs[i].data, &overflow);
if (overflow) {
secp256k1_scalar_clear(&t);
return 0;
}
secp256k1_scalar_add(&t, &t, &s);
}
if (!nonce_parity) {
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_get_b32(sec_adaptor32, &t);
secp256k1_scalar_clear(&t);
return 1;
}
#include "keyagg_impl.h"
#include "session_impl.h"
#include "adaptor_impl.h"
#endif

View File

@ -1,198 +1,63 @@
MuSig - Rogue-Key-Resistant Multisignatures Module
Notes on the musig module API
===========================
This module implements the MuSig [1] multisignature scheme. The majority of
the module is an API designed to be used by signing or auditing participants
in a multisignature scheme. This involves a somewhat complex state machine
and significant effort has been taken to prevent accidental misuse of the
API in ways that could lead to accidental signatures or loss of key material.
The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`).
A usage example can be found in `examples/musig.c`.
The resulting signatures are valid Schnorr signatures as described in [2].
# API misuse
# Theory
The musig API is designed to be as misuse resistant as possible.
However, the MuSig protocol has some additional failure modes (mainly due to interactivity) that do not appear in single-signing.
While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to rule out all such failure modes.
In MuSig all signers contribute key material to a single signing key,
using the equation
Therefore, users of the musig module must take great care to make sure of the following:
P = sum_i µ_i * P_i
1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`.
See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that.
2. The `secp256k1_musig_secnonce` structure is never copied or serialized.
See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`.
3. Opaque data structures are never written to or read from directly.
Instead, only the provided accessor functions are used.
4. If adaptor signatures are used, all partial signatures are verified.
where `P_i` is the public key of the `i`th signer and `µ_i` is a so-called
_MuSig coefficient_ computed according to the following equation
# Key Aggregation and (Taproot) Tweaking
L = H(P_1 || P_2 || ... || P_n)
µ_i = H(L || i)
Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`.
A (Taproot) tweak can be added to the resulting public key with `secp256k1_xonly_pubkey_tweak_add`.
where H is a hash function modelled as a random oracle.
# Signing
To produce a multisignature `(s, R)` on a message `m` using verification key
`P`, signers act as follows:
This is covered by `examples/musig.c`.
Essentially, the protocol proceeds in the following steps:
1. Each computes a nonce, or ephemeral keypair, `(k_i, R_i)`. Every signer
communicates `H(R_i)` to every participant (both signers and auditors).
2. Upon receipt of every `H(R_i)`, each signer communicates `R_i` to every
participant. The recipients check that each `R_i` is consistent with the
previously-communicated hash.
3. Each signer computes a combined nonce
`R = sum_i R_i`
and shared challenge
`e = H(R || P || m)`
and partial signature
`s_i = k_i + µ_i*x_i*e`
where `x_i` is the secret key corresponding to `P_i`.
1. Generate a keypair with `secp256k1_keypair_create` and obtain the xonly public key with `secp256k1_keypair_xonly_pub`.
2. Call `secp256k1_musig_pubkey_agg` with the xonly pubkeys of all participants.
3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_tweak_add`.
4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers.
5. Someone (not necessarily the signer) aggregates the public nonce with `secp256k1_musig_nonce_agg` and sends it to the signers.
6. Process the aggregate nonce with `secp256k1_musig_nonce_process`.
7. Create a partial signature with `secp256k1_musig_partial_sign`.
8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`.
9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`.
The complete signature is then the `(s, R)` where `s = sum_i s_i` and `R = sum_i R_i`.
The aggregate signature can be verified with `secp256k1_schnorrsig_verify`.
# API Usage
Note that steps 1 to 6 can happen before the message to be signed is known to the signers.
Therefore, the communication round to exchange nonces can be viewed as a pre-processing step that is run whenever convenient to the signers.
This disables some of the defense-in-depth measures that may protect against API misuse in some cases.
Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 6).
The following sections describe use of our API, and are mirrored in code in `src/modules/musig/example.c`.
# Verification
It is essential to security that signers use a unique uniformly random nonce for all
signing sessions, and that they do not reuse these nonces even in the case that a
signing session fails to complete. To that end, all signing state is encapsulated
in the data structure `secp256k1_musig_session`. The API does not expose any
functionality to serialize or deserialize this structure; it is designed to exist
only in memory.
A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7.
Users who need to persist this structure must take additional security measures
which cannot be enforced by a C API. Some guidance is provided in the documentation
for this data structure in `include/secp256k1_musig.h`.
## Key Generation
To use MuSig, users must first compute their combined public key `P`, which is
suitable for use on a blockchain or other public key repository. They do this
by calling `secp256k1_musig_pubkey_combine`.
This function takes as input a list of public keys `P_i` in the argument
`pubkeys`. It outputs the combined public key `P` in the out-pointer `combined_pk`
and hash `L` in the out-pointer `pk_hash32`, if this pointer is non-NULL.
## Signing
A participant who wishes to sign a message (as opposed to observing/auditing the
signature process, which is also a supported mode) acts as follows.
### Signing Participant
1. The signer starts the session by calling `secp256k1_musig_session_init`.
This function outputs
- an initialized session state in the out-pointer `session`
- an array of initialized signer data in the out-pointer `signers`
- a commitment `H(R_i)` to a nonce in the out-pointer `nonce_commitment32`
It takes as input
- a unique session ID `session_id32`
- (optionally) a message to be signed `msg32`
- the combined public key output from `secp256k1_musig_pubkey_combine`
- the public key hash output from `secp256k1_musig_pubkey_combine`
- the signer's index `i` `my_index`
- the signer's secret key `seckey`
2. The signer then communicates `H(R_i)` to all other signers, and receives
commitments `H(R_j)` from all other signers `j`. These hashes are simply
length-32 byte arrays which can be communicated however is communicated.
3. Once all signers nonce commitments have been received, the signer records
these commitments with the function `secp256k1_musig_session_get_public_nonce`.
If the signer did not provide a message to `secp256k1_musig_session_init`,
a message must be provided now.
This function updates in place
- the session state `session`
- the array of signer data `signers`
taking in as input the list of commitments `commitments` and outputting the
signer's public nonce `R_i` in the out-pointer `nonce`.
4. The signer then communicates `R_i` to all other signers, and receives `R_j`
from each signer `j`. On receipt of a nonce `R_j` he calls the function
`secp256k1_musig_set_nonce` to record this fact. This function checks that
the received nonce is consistent with the previously-received nonce and will
return 0 in this case. The signer must also call this function with his own
nonce and his own index `i`.
These nonces `R_i` are secp256k1 public keys; they should be serialized using
`secp256k1_ec_pubkey_serialize` and parsed with `secp256k1_ec_pubkey_parse`.
5. Once all nonces have been exchanged in this way, signers are able to compute
their partial signatures. They do so by calling `secp256k1_musig_session_combine_nonces`
which updates in place
- the session state `session`
- the array of signer data `signers`
It outputs an auxiliary integer `nonce_is_negated` and has an auxiliary input
`adaptor`. Both of these may be set to NULL for ordinary signing purposes.
6. The signer computes a partial signature `s_i` using the function
`secp256k1_musig_partial_sign` which takes the session state as input and
partial signature as output.
7. The signer then communicates the partial signature `s_i` to all other signers, or
to a central coordinator. These partial signatures should be serialized using
`musig_partial_signature_serialize` and parsed using `musig_partial_signature_parse`.
8. Each signer calls `secp256k1_musig_partial_sig_verify` on the other signers' partial
signatures to verify their correctness. If only the validity of the final signature
is important, not assigning blame, this step can be skipped.
9. Any signer, or central coordinator, may combine the partial signatures to obtain
a complete signature using `secp256k1_musig_partial_sig_combine`. This function takes
a signing session and array of MuSig partial signatures, and outputs a single
Schnorr signature.
### Non-signing Participant
A participant who wants to verify the signing process, i.e. check that nonce commitments
are consistent and partial signatures are correct without contributing a partial signature,
may do so using the above instructions except for the following changes:
1. A signing session should be produced using `musig_session_init_verifier`
rather than `musig_session_init`; this function takes no secret data or
signer index.
2. The participant receives nonce commitments, public nonces and partial signatures,
but does not produce these values. Therefore `secp256k1_musig_session_get_public_nonce`
and `secp256k1_musig_partial_sign` are not called.
### Verifier
The final signature is simply a valid Schnorr signature using the combined public key. It
can be verified using the `secp256k1_schnorrsig_verify` with the correct message and
public key output from `secp256k1_musig_pubkey_combine`.
## Atomic Swaps
# Atomic Swaps
The signing API supports the production of "adaptor signatures", modified partial signatures
which are offset by an auxiliary secret known to one party. That is,
1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`.
2. When combining nonces, each party adds `T` to the total nonce used in the signature.
3. The party who knows `t` must "adapt" their partial signature with `t` to complete the
signature.
4. Any party who sees both the final signature and the original partial signatures
can compute `t`.
Using these adaptor signatures, two 2-of-2 MuSig signing protocols can be executed in
parallel such that one party's partial signatures are made atomic. That is, when the other
party learns one partial signature, she automatically learns the other. This has applications
in cross-chain atomic swaps.
Such a protocol can be executed as follows. Consider two participants, Alice and Bob, who
are simultaneously producing 2-of-2 multisignatures for two blockchains A and B. They act
as follows.
1. Before the protocol begins, Bob chooses a 32-byte auxiliary secret `t` at random and
computes a corresponding public point `T` by calling `secp256k1_ec_pubkey_create`.
He communicates `T` to Alice.
2. Together, the parties execute steps 1-4 of the signing protocol above.
3. At step 5, when combining the two parties' public nonces, both parties call
`secp256k1_musig_session_combine_nonces` with `adaptor` set to `T` and `nonce_is_negated`
set to a non-NULL pointer to int.
4. Steps 6 and 7 proceed as before. Step 8, verifying the partial signatures, is now
essential to the security of the protocol and must not be omitted!
The above steps are executed identically for both signing sessions. However, step 9 will
not work as before, since the partial signatures will not add up to a valid total signature.
Additional steps must be taken, and it is at this point that the two signing sessions
diverge. From here on we consider "Session A" which benefits Alice (e.g. which sends her
coins) and "Session B" which benefits Bob (e.g. which sends him coins).
5. In Session B, Bob calls `secp256k1_musig_partial_sig_adapt` with his partial signature
and `t`, to produce an adaptor signature. He can then call `secp256k1_musig_partial_sig_combine`
with this adaptor signature and Alice's partial signature, to produce a complete
signature for blockchain B.
6. Alice reads this signature from blockchain B. She calls `secp256k1_musig_extract_secret_adaptor`,
passing the complete signature along with her and Bob's partial signatures from Session B.
This function outputs `t`, which until this point was only known to Bob.
7. In Session A, Alice is now able to replicate Bob's action, calling
`secp256k1_musig_partial_sig_adapt` with her own partial signature and `t`, ultimately
producing a complete signature on blockchain A.
[1] https://eprint.iacr.org/2018/068
[2] https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki
2. When calling `secp256k1_musig_nonce_process`, the public adaptor `T` is provided as the `adaptor` argument.
3. The party who is going to extract the secret adaptor `t` later must verify all partial signatures.
4. Due to step 2, the signature output of `secp256k1_musig_partial_sig_agg` is a pre-signature and not a valid Schnorr signature. All parties involved extract this session's `nonce_parity` with `secp256k1_musig_nonce_parity`.
5. The party who knows `t` must "adapt" the pre-signature with `t` (and the `nonce_parity` using `secp256k1_musig_adapt` to complete the signature.
6. Any party who sees both the final signature and the pre-signature (and has the `nonce_parity`) can extract `t` with `secp256k1_musig_extract_adaptor`.

View File

@ -0,0 +1,25 @@
/***********************************************************************
* Copyright (c) 2021 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_MUSIG_SESSION_H
#define SECP256K1_MODULE_MUSIG_SESSION_H
#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_musig.h"
#include "../../scalar.h"
typedef struct {
int fin_nonce_parity;
unsigned char fin_nonce[32];
secp256k1_scalar noncecoef;
secp256k1_scalar challenge;
secp256k1_scalar s_part;
} secp256k1_musig_session_internal;
static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session);
#endif

View File

@ -0,0 +1,755 @@
/***********************************************************************
* Copyright (c) 2021 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_MUSIG_SESSION_IMPL_H
#define SECP256K1_MODULE_MUSIG_SESSION_IMPL_H
#include <string.h>
#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_extrakeys.h"
#include "../../../include/secp256k1_musig.h"
#include "keyagg.h"
#include "session.h"
#include "../../eckey.h"
#include "../../hash.h"
#include "../../scalar.h"
#include "../../util.h"
static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 };
static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, secp256k1_scalar *k) {
memcpy(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4);
secp256k1_scalar_get_b32(&secnonce->data[4], &k[0]);
secp256k1_scalar_get_b32(&secnonce->data[36], &k[1]);
}
static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_musig_secnonce *secnonce) {
int is_zero;
ARG_CHECK(secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0);
secp256k1_scalar_set_b32(&k[0], &secnonce->data[4], NULL);
secp256k1_scalar_set_b32(&k[1], &secnonce->data[36], NULL);
/* We make very sure that the nonce isn't invalidated by checking the values
* in addition to the magic. */
is_zero = secp256k1_scalar_is_zero(&k[0]) & secp256k1_scalar_is_zero(&k[1]);
secp256k1_declassify(ctx, &is_zero, sizeof(is_zero));
ARG_CHECK(!is_zero);
return 1;
}
/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */
static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) {
secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag);
/* The flag argument is usually classified. So, above code makes the magic
* classified. However, we need the magic to be declassified to be able to
* compare it during secnonce_load. */
secp256k1_declassify(ctx, secnonce->data, sizeof(secp256k1_musig_secnonce_magic));
}
static const unsigned char secp256k1_musig_pubnonce_magic[4] = { 0xf5, 0x7a, 0x3d, 0xa0 };
/* Requires that none of the provided group elements is infinity. Works for both
* musig_pubnonce and musig_aggnonce. */
static void secp256k1_musig_pubnonce_save(secp256k1_musig_pubnonce* nonce, secp256k1_ge* ge) {
int i;
memcpy(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4);
for (i = 0; i < 2; i++) {
secp256k1_point_save(nonce->data + 4+64*i, &ge[i]);
}
}
/* Works for both musig_pubnonce and musig_aggnonce. Returns 1 unless the nonce
* wasn't properly initialized */
static int secp256k1_musig_pubnonce_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_musig_pubnonce* nonce) {
int i;
ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4) == 0);
for (i = 0; i < 2; i++) {
secp256k1_point_load(&ge[i], nonce->data + 4 + 64*i);
}
return 1;
}
static void secp256k1_musig_aggnonce_save(secp256k1_musig_aggnonce* nonce, secp256k1_ge* ge) {
secp256k1_musig_pubnonce_save((secp256k1_musig_pubnonce *) nonce, ge);
}
static int secp256k1_musig_aggnonce_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_musig_aggnonce* nonce) {
return secp256k1_musig_pubnonce_load(ctx, ge, (secp256k1_musig_pubnonce *) nonce);
}
static const unsigned char secp256k1_musig_session_cache_magic[4] = { 0x9d, 0xed, 0xe9, 0x17 };
/* A session consists of
* - 4 byte session cache magic
* - 1 byte the parity of the final nonce
* - 32 byte serialized x-only final nonce
* - 32 byte nonce coefficient b
* - 32 byte signature challenge hash e
* - 32 byte scalar s that is added to the partial signatures of the signers
*/
static void secp256k1_musig_session_save(secp256k1_musig_session *session, const secp256k1_musig_session_internal *session_i) {
unsigned char *ptr = session->data;
memcpy(ptr, secp256k1_musig_session_cache_magic, 4);
ptr += 4;
*ptr = session_i->fin_nonce_parity;
ptr += 1;
memcpy(ptr, session_i->fin_nonce, 32);
ptr += 32;
secp256k1_scalar_get_b32(ptr, &session_i->noncecoef);
ptr += 32;
secp256k1_scalar_get_b32(ptr, &session_i->challenge);
ptr += 32;
secp256k1_scalar_get_b32(ptr, &session_i->s_part);
}
static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session) {
const unsigned char *ptr = session->data;
ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_session_cache_magic, 4) == 0);
ptr += 4;
session_i->fin_nonce_parity = *ptr;
ptr += 1;
memcpy(session_i->fin_nonce, ptr, 32);
ptr += 32;
secp256k1_scalar_set_b32(&session_i->noncecoef, ptr, NULL);
ptr += 32;
secp256k1_scalar_set_b32(&session_i->challenge, ptr, NULL);
ptr += 32;
secp256k1_scalar_set_b32(&session_i->s_part, ptr, NULL);
return 1;
}
static const unsigned char secp256k1_musig_partial_sig_magic[4] = { 0xeb, 0xfb, 0x1a, 0x32 };
static void secp256k1_musig_partial_sig_save(secp256k1_musig_partial_sig* sig, secp256k1_scalar *s) {
memcpy(&sig->data[0], secp256k1_musig_partial_sig_magic, 4);
secp256k1_scalar_get_b32(&sig->data[4], s);
}
static int secp256k1_musig_partial_sig_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_musig_partial_sig* sig) {
int overflow;
ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0);
secp256k1_scalar_set_b32(s, &sig->data[4], &overflow);
/* Parsed signatures can not overflow */
VERIFY_CHECK(!overflow);
return 1;
}
int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_pubnonce* nonce) {
secp256k1_ge ge[2];
int i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(out66 != NULL);
memset(out66, 0, 66);
ARG_CHECK(nonce != NULL);
if (!secp256k1_musig_pubnonce_load(ctx, ge, nonce)) {
return 0;
}
for (i = 0; i < 2; i++) {
int ret;
size_t size = 33;
ret = secp256k1_eckey_pubkey_serialize(&ge[i], &out66[33*i], &size, 1);
/* serialize must succeed because the point was just loaded */
VERIFY_CHECK(ret && size == 33);
}
return 1;
}
int secp256k1_musig_pubnonce_parse(const secp256k1_context* ctx, secp256k1_musig_pubnonce* nonce, const unsigned char *in66) {
secp256k1_ge ge[2];
int i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(nonce != NULL);
ARG_CHECK(in66 != NULL);
for (i = 0; i < 2; i++) {
if (!secp256k1_eckey_pubkey_parse(&ge[i], &in66[33*i], 33)) {
return 0;
}
if (!secp256k1_ge_is_in_correct_subgroup(&ge[i])) {
return 0;
}
}
/* The group elements can not be infinity because they were just parsed */
secp256k1_musig_pubnonce_save(nonce, ge);
return 1;
}
int secp256k1_musig_aggnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_aggnonce* nonce) {
return secp256k1_musig_pubnonce_serialize(ctx, out66, (secp256k1_musig_pubnonce*) nonce);
}
int secp256k1_musig_aggnonce_parse(const secp256k1_context* ctx, secp256k1_musig_aggnonce* nonce, const unsigned char *in66) {
return secp256k1_musig_pubnonce_parse(ctx, (secp256k1_musig_pubnonce*) nonce, in66);
}
int secp256k1_musig_partial_sig_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_sig* sig) {
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(out32 != NULL);
ARG_CHECK(sig != NULL);
memcpy(out32, &sig->data[4], 32);
return 1;
}
int secp256k1_musig_partial_sig_parse(const secp256k1_context* ctx, secp256k1_musig_partial_sig* sig, const unsigned char *in32) {
secp256k1_scalar tmp;
int overflow;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig != NULL);
ARG_CHECK(in32 != NULL);
secp256k1_scalar_set_b32(&tmp, in32, &overflow);
if (overflow) {
return 0;
}
secp256k1_musig_partial_sig_save(sig, &tmp);
return 1;
}
/* Normalizes the x-coordinate of the given group element. */
static int secp256k1_xonly_ge_serialize(unsigned char *output32, secp256k1_ge *ge) {
if (secp256k1_ge_is_infinity(ge)) {
return 0;
}
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_get_b32(output32, &ge->x);
return 1;
}
static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_id, const unsigned char *msg32, const unsigned char *key32, const unsigned char *agg_pk32, const unsigned char *extra_input32) {
secp256k1_sha256 sha;
unsigned char seed[32];
unsigned char i;
enum { n_extra_in = 4 };
const unsigned char *extra_in[n_extra_in];
/* TODO: this doesn't have the same sidechannel resistance as the BIP340
* nonce function because the seckey feeds directly into SHA. */
/* Subtract one from `sizeof` to avoid hashing the implicit null byte */
secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"MuSig/nonce", sizeof("MuSig/nonce") - 1);
secp256k1_sha256_write(&sha, session_id, 32);
extra_in[0] = msg32;
extra_in[1] = key32;
extra_in[2] = agg_pk32;
extra_in[3] = extra_input32;
for (i = 0; i < n_extra_in; i++) {
unsigned char len;
if (extra_in[i] != NULL) {
len = 32;
secp256k1_sha256_write(&sha, &len, 1);
secp256k1_sha256_write(&sha, extra_in[i], 32);
} else {
len = 0;
secp256k1_sha256_write(&sha, &len, 1);
}
}
secp256k1_sha256_finalize(&sha, seed);
for (i = 0; i < 2; i++) {
unsigned char buf[32];
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, seed, 32);
secp256k1_sha256_write(&sha, &i, sizeof(i));
secp256k1_sha256_finalize(&sha, buf);
secp256k1_scalar_set_b32(&k[i], buf, NULL);
}
}
int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *session_id32, const unsigned char *seckey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
secp256k1_keyagg_cache_internal cache_i;
secp256k1_scalar k[2];
secp256k1_ge nonce_pt[2];
int i;
unsigned char pk_ser[32];
unsigned char *pk_ser_ptr = NULL;
int ret = 1;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secnonce != NULL);
memset(secnonce, 0, sizeof(*secnonce));
ARG_CHECK(pubnonce != NULL);
memset(pubnonce, 0, sizeof(*pubnonce));
ARG_CHECK(session_id32 != NULL);
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
if (seckey == NULL) {
/* Check in constant time that the session_id is not 0 as a
* defense-in-depth measure that may protect against a faulty RNG. */
unsigned char acc = 0;
for (i = 0; i < 32; i++) {
acc |= session_id32[i];
}
ret &= !!acc;
memset(&acc, 0, sizeof(acc));
}
/* Check that the seckey is valid to be able to sign for it later. */
if (seckey != NULL) {
secp256k1_scalar sk;
ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey);
secp256k1_scalar_clear(&sk);
}
if (keyagg_cache != NULL) {
int ret_tmp;
if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
return 0;
}
ret_tmp = secp256k1_xonly_ge_serialize(pk_ser, &cache_i.pk);
/* Serialization can not fail because the loaded point can not be infinity. */
VERIFY_CHECK(ret_tmp);
pk_ser_ptr = pk_ser;
}
secp256k1_nonce_function_musig(k, session_id32, msg32, seckey, pk_ser_ptr, extra_input32);
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0]));
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1]));
VERIFY_CHECK(!secp256k1_scalar_eq(&k[0], &k[1]));
secp256k1_musig_secnonce_save(secnonce, k);
secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret);
for (i = 0; i < 2; i++) {
secp256k1_gej nonce_ptj;
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]);
secp256k1_ge_set_gej(&nonce_pt[i], &nonce_ptj);
secp256k1_declassify(ctx, &nonce_pt[i], sizeof(nonce_pt));
secp256k1_scalar_clear(&k[i]);
}
/* nonce_pt won't be infinity because k != 0 with overwhelming probability */
secp256k1_musig_pubnonce_save(pubnonce, nonce_pt);
return ret;
}
static int secp256k1_musig_sum_nonces(const secp256k1_context* ctx, secp256k1_gej *summed_nonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) {
size_t i;
int j;
secp256k1_gej_set_infinity(&summed_nonces[0]);
secp256k1_gej_set_infinity(&summed_nonces[1]);
for (i = 0; i < n_pubnonces; i++) {
secp256k1_ge nonce_pt[2];
if (!secp256k1_musig_pubnonce_load(ctx, nonce_pt, pubnonces[i])) {
return 0;
}
for (j = 0; j < 2; j++) {
secp256k1_gej_add_ge_var(&summed_nonces[j], &summed_nonces[j], &nonce_pt[j], NULL);
}
}
return 1;
}
int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggnonce *aggnonce, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) {
secp256k1_gej aggnonce_ptj[2];
secp256k1_ge aggnonce_pt[2];
int i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(aggnonce != NULL);
ARG_CHECK(pubnonces != NULL);
ARG_CHECK(n_pubnonces > 0);
if (!secp256k1_musig_sum_nonces(ctx, aggnonce_ptj, pubnonces, n_pubnonces)) {
return 0;
}
for (i = 0; i < 2; i++) {
if (secp256k1_gej_is_infinity(&aggnonce_ptj[i])) {
/* There must be at least one dishonest signer. If we would return 0
here, we will never be able to determine who it is. Therefore, we
should continue such that the culprit is revealed when collecting
and verifying partial signatures.
However, dealing with the point at infinity (loading,
de-/serializing) would require a lot of extra code complexity.
Instead, we set the aggregate nonce to some arbitrary point (the
generator). This is secure, because it only restricts the
abilities of the attacker: an attacker that forces the sum of
nonces to be infinity by sending some maliciously generated nonce
pairs can be turned into an attacker that forces the sum to be
the generator (by simply adding the generator to one of the
malicious nonces), and this does not change the winning condition
of the EUF-CMA game. */
aggnonce_pt[i] = secp256k1_ge_const_g;
} else {
secp256k1_ge_set_gej(&aggnonce_pt[i], &aggnonce_ptj[i]);
}
}
secp256k1_musig_aggnonce_save(aggnonce, aggnonce_pt);
return 1;
}
/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */
static int secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) {
unsigned char buf[33];
secp256k1_sha256 sha;
int i;
secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"MuSig/noncecoef", sizeof("MuSig/noncecoef") - 1);
for (i = 0; i < 2; i++) {
size_t size;
if (!secp256k1_eckey_pubkey_serialize(&aggnonce[i], buf, &size, 1)) {
return 0;
}
VERIFY_CHECK(size == sizeof(buf));
secp256k1_sha256_write(&sha, buf, sizeof(buf));
}
secp256k1_sha256_write(&sha, agg_pk32, 32);
secp256k1_sha256_write(&sha, msg, 32);
secp256k1_sha256_finalize(&sha, noncehash);
return 1;
}
static int secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_gej *aggnoncej, const unsigned char *agg_pk32, const unsigned char *msg) {
unsigned char noncehash[32];
secp256k1_ge fin_nonce_pt;
secp256k1_gej fin_nonce_ptj;
secp256k1_ge aggnonce[2];
secp256k1_ge_set_gej(&aggnonce[0], &aggnoncej[0]);
secp256k1_ge_set_gej(&aggnonce[1], &aggnoncej[1]);
if (!secp256k1_musig_compute_noncehash(noncehash, aggnonce, agg_pk32, msg)) {
return 0;
}
/* fin_nonce = aggnonce[0] + b*aggnonce[1] */
secp256k1_scalar_set_b32(b, noncehash, NULL);
secp256k1_ecmult(&fin_nonce_ptj, &aggnoncej[1], b, NULL);
secp256k1_gej_add_ge(&fin_nonce_ptj, &fin_nonce_ptj, &aggnonce[0]);
secp256k1_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj);
if (!secp256k1_xonly_ge_serialize(fin_nonce, &fin_nonce_pt)) {
/* unreachable with overwhelming probability */
return 0;
}
secp256k1_fe_normalize_var(&fin_nonce_pt.y);
*fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y);
return 1;
}
int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey *adaptor) {
secp256k1_keyagg_cache_internal cache_i;
secp256k1_ge aggnonce_pt[2];
secp256k1_gej aggnonce_ptj[2];
unsigned char fin_nonce[32];
secp256k1_musig_session_internal session_i;
unsigned char agg_pk32[32];
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(aggnonce != NULL);
ARG_CHECK(msg32 != NULL);
ARG_CHECK(keyagg_cache != NULL);
if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
return 0;
}
secp256k1_fe_get_b32(agg_pk32, &cache_i.pk.x);
if (!secp256k1_musig_aggnonce_load(ctx, aggnonce_pt, aggnonce)) {
return 0;
}
secp256k1_gej_set_ge(&aggnonce_ptj[0], &aggnonce_pt[0]);
secp256k1_gej_set_ge(&aggnonce_ptj[1], &aggnonce_pt[1]);
/* Add public adaptor to nonce */
if (adaptor != NULL) {
secp256k1_ge adaptorp;
if (!secp256k1_pubkey_load(ctx, &adaptorp, adaptor)) {
return 0;
}
secp256k1_gej_add_ge_var(&aggnonce_ptj[0], &aggnonce_ptj[0], &adaptorp, NULL);
}
if (!secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_ptj, agg_pk32, msg32)) {
return 0;
}
secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32);
/* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/
secp256k1_scalar_set_int(&session_i.s_part, 0);
if (!secp256k1_scalar_is_zero(&cache_i.tweak)) {
secp256k1_scalar e_tmp;
secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak);
if (secp256k1_fe_is_odd(&cache_i.pk.y)) {
secp256k1_scalar_negate(&e_tmp, &e_tmp);
}
secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &e_tmp);
}
memcpy(session_i.fin_nonce, fin_nonce, sizeof(session_i.fin_nonce));
secp256k1_musig_session_save(session, &session_i);
return 1;
}
void secp256k1_musig_partial_sign_clear(secp256k1_scalar *sk, secp256k1_scalar *k) {
secp256k1_scalar_clear(sk);
secp256k1_scalar_clear(&k[0]);
secp256k1_scalar_clear(&k[1]);
}
int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_partial_sig *partial_sig, secp256k1_musig_secnonce *secnonce, const secp256k1_keypair *keypair, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) {
secp256k1_scalar sk;
secp256k1_ge pk;
secp256k1_scalar k[2];
secp256k1_scalar mu, s;
secp256k1_keyagg_cache_internal cache_i;
secp256k1_musig_session_internal session_i;
int ret;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secnonce != NULL);
/* Fails if the magic doesn't match */
ret = secp256k1_musig_secnonce_load(ctx, k, secnonce);
/* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls
* of this function to fail */
memset(secnonce, 0, sizeof(*secnonce));
if (!ret) {
secp256k1_musig_partial_sign_clear(&sk, k);
return 0;
}
ARG_CHECK(partial_sig != NULL);
ARG_CHECK(keypair != NULL);
ARG_CHECK(keyagg_cache != NULL);
ARG_CHECK(session != NULL);
if (!secp256k1_keypair_load(ctx, &sk, &pk, keypair)) {
secp256k1_musig_partial_sign_clear(&sk, k);
return 0;
}
if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
secp256k1_musig_partial_sign_clear(&sk, k);
return 0;
}
secp256k1_fe_normalize_var(&pk.y);
/* Determine if the secret key sk should be negated before signing.
*
* We use the following notation:
* - |.| is a function that normalizes a point to an even Y by negating
* if necessary, similar to secp256k1_extrakeys_ge_even_y
* - mu[i] is the i-th KeyAgg coefficient
* - t[i] is the i-th tweak
*
* The following public keys arise as intermediate steps:
* - P[i] is the i-th public key with corresponding secret key x[i]
* P[i] := x[i]*G
* - P_agg is the aggregate public key
* P_agg := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
* - P_tweak[i] is the tweaked public key after the i-th tweaking operation
* P_tweak[0] := P_agg
* P_tweak[i] := |P_tweak[i-1]| + t[i]*G for i = 1, ..., m
*
* Note that our goal is to produce a partial signature corresponding to
* the final public key after m tweaking operations P_final = |P_tweak[m]|.
*
* Define d[i], d_agg, and d_tweak[i] so that:
* - |P[i]| = d[i]*P[i]
* - |P_agg| = d_agg*P_agg
* - |P_tweak[i]| = d_tweak[i]*P_tweak[i]
*
* In other words, d[i] = 1 if P[i] has even y coordinate, -1 otherwise;
* similarly for d_agg and d_tweak[i].
*
* The (xonly) final public key is P_final = |P_tweak[m]|
* = d_tweak[m]*P_tweak[m]
* = d_tweak[m]*(|P_tweak[m-1]| + t[m]*G)
* = d_tweak[m]*(d_tweak[m-1]*(|P_tweak[m-2]| + t[m-1]*G) + t[m]*G)
* = d_tweak[m]*...*d_tweak[1]*|P_agg| + (d_tweak[m]*t[m]+...+*d_tweak[1]*t[1])*G.
* To simplify the equation let us define
* t := d_tweak[m]*t[m]+...+*d_tweak[1]*t[1]
* d_tweak := d_tweak[m]*...*d_tweak[1].
* Then we have
* P_final - t*G
* = d_tweak*|P_agg|
* = d_tweak*d_agg*P_agg
* = d_tweak*d_agg*(mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|)
* = d_tweak*d_agg*(d[0]*mu[0]*P[0] + ... + d[n-1]*mu[n-1]*P[n-1])
* = sum((d_tweak*d_agg*d[i])*mu[i]*x[i])*G.
*
* Thus whether signer i should use the negated x[i] depends on the product
* d_tweak[m]*...*d_tweak[1]*d_agg*d[i]. In other words, negate if and only
* if the following holds:
* (P[i] has odd y) XOR (P_agg has odd y)
* XOR (P_tweak[1] has odd y) XOR ... XOR (P_tweak[m] has odd y)
*
* Let us now look at how the terms in the equation correspond to the if
* condition below for some values of m:
* m = 0: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
* P_agg has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
* cache_i.internal_key_parity = 0
* m = 1: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
* P_agg has odd y = cache_i.internal_key_parity
* P_tweak[1] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
* m = 2: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
* P_agg has odd y XOR P_tweak[1] has odd y = cache_i.internal_key_parity
* P_tweak[2] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
* etc.
*/
if ((secp256k1_fe_is_odd(&pk.y)
!= secp256k1_fe_is_odd(&cache_i.pk.y))
!= cache_i.internal_key_parity) {
secp256k1_scalar_negate(&sk, &sk);
}
/* Multiply KeyAgg coefficient */
secp256k1_fe_normalize_var(&pk.x);
/* TODO Cache mu */
secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk.x);
secp256k1_scalar_mul(&sk, &sk, &mu);
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
secp256k1_musig_partial_sign_clear(&sk, k);
return 0;
}
if (session_i.fin_nonce_parity) {
secp256k1_scalar_negate(&k[0], &k[0]);
secp256k1_scalar_negate(&k[1], &k[1]);
}
/* Sign */
secp256k1_scalar_mul(&s, &session_i.challenge, &sk);
secp256k1_scalar_mul(&k[1], &session_i.noncecoef, &k[1]);
secp256k1_scalar_add(&k[0], &k[0], &k[1]);
secp256k1_scalar_add(&s, &s, &k[0]);
secp256k1_musig_partial_sig_save(partial_sig, &s);
secp256k1_musig_partial_sign_clear(&sk, k);
return 1;
}
int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_musig_partial_sig *partial_sig, const secp256k1_musig_pubnonce *pubnonce, const secp256k1_xonly_pubkey *pubkey, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) {
secp256k1_keyagg_cache_internal cache_i;
secp256k1_musig_session_internal session_i;
secp256k1_scalar mu, e, s;
secp256k1_gej pkj;
secp256k1_ge nonce_pt[2];
secp256k1_gej rj;
secp256k1_gej tmp;
secp256k1_ge pkp;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(partial_sig != NULL);
ARG_CHECK(pubnonce != NULL);
ARG_CHECK(pubkey != NULL);
ARG_CHECK(keyagg_cache != NULL);
ARG_CHECK(session != NULL);
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
return 0;
}
/* Compute "effective" nonce rj = aggnonce[0] + b*aggnonce[1] */
/* TODO: use multiexp to compute -s*G + e*mu*pubkey + aggnonce[0] + b*aggnonce[1] */
if (!secp256k1_musig_pubnonce_load(ctx, nonce_pt, pubnonce)) {
return 0;
}
secp256k1_gej_set_ge(&rj, &nonce_pt[1]);
secp256k1_ecmult(&rj, &rj, &session_i.noncecoef, NULL);
secp256k1_gej_add_ge_var(&rj, &rj, &nonce_pt[0], NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pkp, pubkey)) {
return 0;
}
if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
return 0;
}
/* Multiplying the challenge by the KeyAgg coefficient is equivalent
* to multiplying the signer's public key by the coefficient, except
* much easier to do. */
secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp.x);
secp256k1_scalar_mul(&e, &session_i.challenge, &mu);
/* If the MuSig-aggregate point has an odd Y coordinate, the signers will
* sign for the negation of their individual xonly public key. If the
* aggregate key is untweaked, then internal_key_parity is 0, so `e` is
* negated exactly when the aggregate key parity is odd. If the aggregate
* key is tweaked, then negation happens when the aggregate key has an odd Y
* coordinate XOR the internal key has an odd Y coordinate.*/
/* When producing a partial signature, signer i uses a possibly
* negated secret key:
*
* sk[i] = (d_tweak*d_agg*d[i])*x[i]
*
* to ensure that the aggregate signature will correspond to
* an aggregate public key with even Y coordinate (see the
* notation and explanation in musig_partial_sign).
*
* We use the following additional notation:
* - e is the (Schnorr signature) challenge
* - r[i] is the i-th signer's secret nonce
* - R[i] = r[i]*G is the i-th signer's public nonce
* - R is the aggregated public nonce
* - d_nonce is chosen so that |R| = d_nonce*R
*
* The i-th partial signature is:
*
* s[i] = d_nonce*r[i] + mu[i]*e*sk[i]
*
* In order to verify this partial signature, we need to check:
*
* s[i]*G = d_nonce*R[i] + mu[i]*e*sk[i]*G
*
* The verifier doesn't have access to sk[i]*G, but can construct
* it using the xonly public key |P[i]| as follows:
*
* sk[i]*G = d_tweak*d_agg*d[i]*x[i]*G
* = d_tweak*d_agg*d[i]*P[i]
* = d_tweak*d_agg*|P[i]|
*
* The if condition below is true whenever d_tweak*d_agg is
* negative (again, see the explanation in musig_partial_sign). In
* this case, the verifier negates e which will have the same end
* result as negating |P[i]|, since they are multiplied later anyway.
*/
if (secp256k1_fe_is_odd(&cache_i.pk.y)
!= cache_i.internal_key_parity) {
secp256k1_scalar_negate(&e, &e);
}
if (!secp256k1_musig_partial_sig_load(ctx, &s, partial_sig)) {
return 0;
}
/* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */
secp256k1_scalar_negate(&s, &s);
secp256k1_gej_set_ge(&pkj, &pkp);
secp256k1_ecmult(&tmp, &pkj, &e, &s);
if (session_i.fin_nonce_parity) {
secp256k1_gej_neg(&rj, &rj);
}
secp256k1_gej_add_var(&tmp, &tmp, &rj, NULL);
return secp256k1_gej_is_infinity(&tmp);
}
int secp256k1_musig_partial_sig_agg(const secp256k1_context* ctx, unsigned char *sig64, const secp256k1_musig_session *session, const secp256k1_musig_partial_sig * const* partial_sigs, size_t n_sigs) {
size_t i;
secp256k1_musig_session_internal session_i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig64 != NULL);
ARG_CHECK(session != NULL);
ARG_CHECK(partial_sigs != NULL);
ARG_CHECK(n_sigs > 0);
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
return 0;
}
for (i = 0; i < n_sigs; i++) {
secp256k1_scalar term;
if (!secp256k1_musig_partial_sig_load(ctx, &term, partial_sigs[i])) {
return 0;
}
secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &term);
}
secp256k1_scalar_get_b32(&sig64[32], &session_i.s_part);
memcpy(&sig64[0], session_i.fin_nonce, 32);
return 1;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
#include <valgrind/memcheck.h>
#include <stdio.h>
#include <string.h>
#include "../include/secp256k1.h"
#include "assumptions.h"
@ -35,6 +36,10 @@
#include "include/secp256k1_ecdsa_adaptor.h"
#endif
#ifdef ENABLE_MODULE_MUSIG
#include "include/secp256k1_musig.h"
#endif
void run_tests(secp256k1_context *ctx, unsigned char *key);
int main(void) {
@ -241,4 +246,70 @@ void run_tests(secp256k1_context *ctx, unsigned char *key) {
CHECK(ret == 0);
}
#endif
#ifdef ENABLE_MODULE_MUSIG
{
secp256k1_xonly_pubkey pk;
const secp256k1_xonly_pubkey *pk_ptr[1];
secp256k1_xonly_pubkey agg_pk;
unsigned char session_id[32];
secp256k1_musig_secnonce secnonce;
secp256k1_musig_pubnonce pubnonce;
const secp256k1_musig_pubnonce *pubnonce_ptr[1];
secp256k1_musig_aggnonce aggnonce;
secp256k1_musig_keyagg_cache cache;
secp256k1_musig_session session;
secp256k1_musig_partial_sig partial_sig;
const secp256k1_musig_partial_sig *partial_sig_ptr[1];
unsigned char extra_input[32];
unsigned char sec_adaptor[32];
secp256k1_pubkey adaptor;
unsigned char pre_sig[64];
int nonce_parity;
pk_ptr[0] = &pk;
pubnonce_ptr[0] = &pubnonce;
VALGRIND_MAKE_MEM_DEFINED(key, 32);
memcpy(session_id, key, sizeof(session_id));
session_id[0] = session_id[0] + 1;
memcpy(extra_input, key, sizeof(extra_input));
extra_input[0] = extra_input[0] + 2;
memcpy(sec_adaptor, key, sizeof(sec_adaptor));
sec_adaptor[0] = extra_input[0] + 3;
partial_sig_ptr[0] = &partial_sig;
CHECK(secp256k1_keypair_create(ctx, &keypair, key));
CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
CHECK(secp256k1_musig_pubkey_agg(ctx, NULL, &agg_pk, &cache, pk_ptr, 1));
CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor));
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(session_id, sizeof(session_id));
VALGRIND_MAKE_MEM_UNDEFINED(extra_input, sizeof(extra_input));
VALGRIND_MAKE_MEM_UNDEFINED(sec_adaptor, sizeof(sec_adaptor));
ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_id, key, msg, &cache, extra_input);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1));
CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache, &adaptor) == 1);
ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
VALGRIND_MAKE_MEM_DEFINED(&partial_sig, sizeof(partial_sig));
CHECK(secp256k1_musig_partial_sig_agg(ctx, pre_sig, &session, partial_sig_ptr, 1));
VALGRIND_MAKE_MEM_DEFINED(pre_sig, sizeof(pre_sig));
CHECK(secp256k1_musig_nonce_parity(ctx, &nonce_parity, &session));
ret = secp256k1_musig_adapt(ctx, sig, pre_sig, sec_adaptor, nonce_parity);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
ret = secp256k1_musig_extract_adaptor(ctx, sec_adaptor, sig, pre_sig, nonce_parity);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
}
#endif
}