Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

musig-spec: expand on signing flow #176

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 53 additions & 18 deletions doc/musig-spec.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ MuSig2 stands out by combining the following features:
* '''Non-interactive signing with preprocessing''': The first communication round, exchanging the nonces, can happen before the message or even the exact set of signers is determined. Therefore, the signers can view it as a preprocessing step. Later, when the parameters of the signing session are chosen, they can send partial signatures without additional interaction.
* '''Key aggregation optionally independent of order''': The output of the key aggregation algorithm depends on the order of the input public keys. The specification defines an algorithm to sort the public keys before key aggregation. This will ensure the same output, independent of the initial order. Key aggregation does not sort the public keys by default because applications often already have a common order of signers. Then, sorting is unnecessary and very slow for a large set of signers compared to the rest of the MuSig2 protocol. In the worst case, sorting algorithms in standard libraries can have quadratic run time, which is undesirable in adversarial settings. Nonetheless, standards using this specification can mandate sorting before aggregation. Note that the key aggregation coefficient is computed by hashing the public key instead of its index, which requires one more invocation of the SHA-256 compression function. However, it results in significantly simpler implementations because signers do not need to translate between public key indices before and after sorting.
* '''Third party nonce aggregation''': Instead of every signer sending their nonce to every other signer, it is possible to use an untrusted third party that collects all signers' nonces, computes an aggregate nonce, and broadcasts it to the signers. This reduces the communication complexity from quadratic to linear in the number of signers. If the aggregator sends an incorrect aggregate nonce, the signing session will fail to produce a valid Schnorr signature. However, the aggregator cannot negatively affect the security of the scheme.
* '''Partial signature verification''': If any signer sends a partial signature contribution that was not created by honestly following the protocol, the signing session will fail to produce a valid Schnorr signature. This standard specifies a partial signature verification algorithm to identify disruptive signers. It is incompatible with third-party nonce aggregation because it would be impossible to tell if a signer or the aggregator is to blame.
* '''Partial signature verification''': If any signer sends a partial signature contribution that was not created by honestly following the protocol, the signing session will fail to produce a valid Schnorr signature. This standard specifies a partial signature verification algorithm to identify disruptive signers. It is incompatible with third-party nonce aggregation because the individual nonce is required for partial verification.
* '''MuSig2* optimization''': The specification uses an optimization that allows saving a point multiplication in key aggregation. The MuSig2 scheme with this optimization is called MuSig2* and proven secure in the appendix of the [https://eprint.iacr.org/2020/1261 MuSig2 paper]. The optimization is that the second key in the list of public keys given to the key aggregation algorithm (as well as any keys identical to this key) gets the constant key aggregation coefficient ''1''.
* '''Parameterization of MuSig2 and security''': In this specification, each signer's nonce consists of two elliptic curve points. The [https://eprint.iacr.org/2020/1261 MuSig2 paper] gives distinct security proofs depending on the number of points that constitute a nonce. See section [[#choosing-the-size-of-the-nonce|Choosing the Size of the Nonce]] for a discussion.

Expand All @@ -57,6 +57,57 @@ Also, the signers' public nonces are serialized in compressed format (33 bytes)

When implementing the specification, make sure to understand this section thoroughly, particularly the [[#signing-flow|Signing Flow]], to avoid subtle mistakes that lead to catastrophic failure.

=== Signing Flow ===

The basic order of operations to create a multi-signature with the specification is as follows:
The signers start by exchanging public keys and computing an aggregate public key using the ''KeyAgg'' algorithm.
When they want to sign a message, each signer starts the signing session by running ''NonceGen'' to compute ''secnonce'' and ''pubnonce''.
Then, the signers broadcast their ''pubnonce'' to each other and run ''NonceAgg'' to compute an aggregate nonce.
At this point, every signer has the required data to sign, which, in the specification, is stored in a data structure called [[#session-context|Session Context]].
After running ''Sign'' with the secret signing key, the ''secnonce'' and the session context, each signer sends their partial signature to an aggregator node, which produces a final signature using ''PartialSigAgg''.
If all signers behaved honestly, the result passes [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340] verification.

'''IMPORTANT''': The ''Sign'' algorithm must '''not''' be executed twice with the same ''secnonce''.
Otherwise, extracting the secret signing key from the partial signatures is possible.
To avoid accidental reuse, an implementation may securely erase the ''secnonce'' argument by overwriting it with zeros after ''Sign'' has been run.
A ''secnonce'' consisting of only zeros is invalid for ''Sign'' and will cause it to fail.
The ''NonceGen'' algorithm '''must''' draw unbiased, uniformly random values ''k<sub>1</sub>'' and ''k<sub>2</sub>''.
In particular, ''k<sub>1</sub>'' and ''k<sub>2</sub>'' must _not_ be derived deterministically from the session parameters (see [[#nonce-generation|Nonce Generation]]).

The output of ''KeyAgg'' is dependent on the order of the input public keys.
If there is no common order of the signers already, the public keys can be sorted with the ''KeySort'' algorithm to ensure that the same aggregate key is calculated.
Note that public keys are allowed to occur multiple times in the input of ''KeyAgg'' and ''KeySort'', and that it is possible to successfully complete a MuSig2 signing session with duplicated public keys.

In some applications, it is beneficial to generate and exchange ''pubnonces'' before the message to sign or the final set of signers is known.
After this preprocessing phase, the ''Sign'' algorithm can be run immediately when the message and set of signers is determined.
This way, the final signature is created quicker and with fewer roundtrips.
However, applications that use this method presumably store the nonces for a longer time and must therefore be even more careful not to reuse them.
Moreover, this method prohibits a defense-in-depth measure that strengthens [[#nonce-generation|Nonce Generation]].

Instead of every signer broadcasting their ''pubnonce'' to every other signer, the signers can send their ''pubnonce'' to a single aggregator node that runs ''NonceAgg'' and sends the ''aggnonce'' back to the signers.
This technique reduces the overall communication.
The aggregator node does not need to be trusted for the scheme's security to hold.
All the aggregator node can do is prevent the signing session from succeeding by sending out incorrect aggregate nonces.

If any signer sends an incorrect partial signature, i.e., one that has not then been created with ''Sign'' and the right arguments for the session, the MuSig2 protocol may fail to output a valid Schnorr signature.
This standard provides the method ''PartialSigVerify'' to verify the correctness of partial signatures.
If partial signatures are authenticated, this method can be used to identify disruptive signers and hold them accountable.
Note that partial signatures are ''not'' signatures.
An adversary can forge a partial signature, i.e., create a partial signature without knowing the secret key for the claimed public key<ref>Assume an adversary wants to forge a partial signature for public key ''P''. It joins the signing session pretending to be two different signers, one with public key ''P' and one with another public key. The adversary can then set the second signer's nonce such that it will be able to produce a partial signature for ''P'', but not for the other claimed signer.</ref>.
However, if ''PartialSigVerify'' succeeds for all partial signatures then ''PartialSigAgg'' will return a valid Schnorr signature.

To simplify the specification, some intermediary values are unnecessarily recomputed from scratch, e.g., when executing ''GetSessionValues'' multiple times.
Actual implementations can cache these values.
As a result, the [[#session-context|Session Context]] may look very different in implementations or may not exist at all.

==== Nonce Generation ====

TODO

==== Tweaking ====

TODO

=== Notation ===

The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]. We note that adapting this specification to other elliptic curves is not straightforward and can result in an insecure scheme.
Expand Down Expand Up @@ -288,30 +339,14 @@ Input:
* Let ''s = s<sub>1</sub> + ... + s<sub>u</sub> + e⋅g<sub>v</sub>⋅tacc<sub>v</sub> mod n''
* Return ''sig = ''bytes(R) || bytes(s)''

=== Signing Flow ===

Note that this specification unnecessarily recomputes intermediary values (such as the aggregate and tweaked public key) that can be cached in real implementations.

There are multiple ways to use above algorithms and arrive at a final Schnorr signature.
One of them can be described as follows:
The signers ''1'' to ''n'' each run ''NonceGen'' to compute ''secnonce'' and ''pubnonce''.
Every signer sends its public key and ''pubnonce'' to every other signer and all signers agree on a single message to sign.
Then, the signers run ''NonceAgg'' and ''Sign'' with their secret signing key and ''secnonce''.
They send the resulting partial signature to every other signer and combine them with the ''PartialSigAgg'' algorithm.

''IMPORTANT'': The ''Sign'' algorithm must '''not''' be executed twice with the same ''secnonce''.
Otherwise, it is possible to extract the secret signing key from the partial signatures.
An implementation may invalidate the secnonce argument after ''Sign'' to avoid any reuse.
Avoiding reuse also implies that the ''NonceGen'' algorithm must compute unbiased, uniformly random values ''k<sub>1</sub>'' and ''k<sub>2</sub>''.

=== Test Vectors and Reference Code ===

There are some vectors in libsecp256k1's [https://github.com/ElementsProject/secp256k1-zkp/blob/master/src/modules/musig/tests_impl.h MuSig test file].
Search for the ''musig_test_vectors_keyagg'' and ''musig_test_vectors_sign'' functions.

== Remarks on Security and Correctness ==

=== Tweaking ===
=== Tweaking Definition ===

This MuSig2 specification supports two modes of tweaking that correspond to the following algorithms:

Expand Down