Merge ElementsProject/secp256k1-zkp#131: Replace MuSig(1) module with MuSig2

ac1e36769d musig: turn off multiexponentiation for now (Jonas Nick)
3c79d97bd9 ci: increase timeout for macOS tasks (Jonas Nick)
22c88815c7 musig: replace MuSig(1) with MuSig2 (Jonas Nick)

Pull request description:

  The main commit comprises `905 insertions(+), 1253 deletions(-)`. The diff isn't as small as I had hoped, but that's mostly because it was possible to simplify the API quite substantially which required rewriting large parts. Sorry, almost all of the changes are in one big commit which makes the diff very hard to read. Perhaps best to re-review most parts from scratch.

  A few key changes:

  - Obviously no commitment round. No big session struct and no `verifier` sessions. No `signer` struct.
  - There's a new `secnonce` struct that is the output of musig_nonce_gen and derived from a uniformly random session_id32. The derivation can be strengthened by adding whatever session parameters (combined_pk, msg) are available. The nonce function is my ad-hoc construction that allows for these optional inputs. Please have a look at that.
  - The secnonce is made invalid after being used in partial_sign.
  - Adaptor signatures basically work as before, according to https://github.com/ElementsProject/scriptless-scripts/pull/24 (with the exception that they operate on aggregate instead of partial sigs)
  - To avoid making this PR overly complex I did not consider how this implementation interacts with nested-MuSig, sign-to-contract, and antiklepto.
  - Testing should be close to complete. There's no reachable line or branch that isn't exercised by the tests.
  - [x] ~In the current implementation when a signer sends an invalid nonce (i.e. some garbage that can't be mapped to a group element), it is ignored when combining nonces. Only after receiving the signers partial signature and running `partial_sig_verify` will we notice that the signer misbehaved. The reason for this is that 1) this makes the API simpler and 2) malicious peers don't gain any additional powers because they can always interrupt the protocol by refusing to sign. However, this is up for discussion.~ EDIT: this is not the case anymore since invalid nonces are rejected when they're parsed.
  - [x] ~For every partial signature we verify we have to parse the pubnonce (two compressed points), despite having parsed it in `process_nonces` already. This is not great. `process_nonces` could optionally output the array of parsed pubnonces.~ EDIT: fixed by having a dedicated type for nonces.
  - [x] ~I left `src/modules/musig/musig.md` unchanged for now. Perhaps we should merge it with the `musig-spec`~ EDIT: musig.md is updated
  - [x] partial verification should use multiexp to compute `R1 + b*R2 + c*P`, but this can be done in a separate PR
  - [x] renaming wishlist
      - pre_session -> keyagg_cache (because there is no session anymore)
      - pubkey_combine, nonce_combine, partial_sig_combine -> pubkey_agg, nonce_agg, partial_sig_agg (shorter, matches terminology in musig2)
      - musig_session_init -> musig_start (shorter, simpler) or [musig_generate_nonce](https://github.com/ElementsProject/secp256k1-zkp/pull/131#discussion_r654190890) or musig_prepare
      - musig_partial_signature to musig_partial_sig (shorter)
  - [x] perhaps remove pubnonces and n_pubnonces argument from process_nonces (and then also add a opaque type for the combined nonce?)
  - [x] write the `combined_pubkey` into the `pre_session` struct (as suggested [below](https://github.com/ElementsProject/secp256k1-zkp/pull/131#issuecomment-866904975): then 1) session_init and process_nonces don't need a combined_pk argument (and there can't be mix up between tweaked and untweaked keys) and 2) pubkey_tweak doesn't need an input_pubkey and the output_pubkey can be written directly into the pre_session (reducing frustration such as Replace MuSig(1) module with MuSig2 #131 (comment))
  - [x] perhaps allow adapting both partial sigs (`partial_sig` struct) and aggregate partial sigs (64 raw bytes) as suggested [below](https://github.com/ElementsProject/secp256k1-zkp/pull/131#issuecomment-867281531).

  Based on #120.

ACKs for top commit:
  robot-dreams:
    ACK ac1e36769d
  real-or-random:
    ACK ac1e36769d

Tree-SHA512: 916b42811aa5c00649cfb923d2002422c338106a6936a01253ba693015a242f21f7f7b4cce60d5ab5764a129926c6fd6676977c69c9e6e0aedc51b308ac6578d
This commit is contained in:
Tim Ruffing
2021-12-20 15:11:44 +01:00
16 changed files with 2893 additions and 2258 deletions

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,339 @@ 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: should be NULL because it is not yet implemented. If it
* was implemented then the scratch space would be 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);