secp256k1-zkp/doc/musig-spec.mediawiki

295 lines
18 KiB
Plaintext
Raw Normal View History

2021-01-12 14:21:20 +00:00
<pre>
Title: MuSig
2021-01-12 14:21:20 +00:00
Author:
Status: Draft
License: BSD-2-Clause
Created: 2020-01-19
</pre>
== Introduction ==
=== Abstract ===
This document proposes a standard for the MuSig2 protocol that supports ''tweaking'' and outputs [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340] public keys and signatures.
2021-01-12 14:21:20 +00:00
=== Copyright ===
This document is licensed under the 2-clause BSD license.
=== Motivation ===
== Description ==
=== Design ===
* The output of the ''KeyAgg'' algorithm depends on the order of the input public keys.
* It is possible to sort the public keys with the ''KeySort'' algorithm before key aggregation to ensure the same output, independent of the (initial) order.
2021-01-12 14:21:20 +00:00
* The KeyAgg coefficient is computed by hashing the key instead of key index. Otherwise, if the pubkey list gets sorted, the signer needs to translate between key indices pre- and post-sorting.
* The second unique key in the pubkey list given to ''KeyAgg'' (as well as any keys identical to this key) gets the constant KeyAgg coefficient 1 which saves an exponentiation (see the MuSig2* appendix in the [https://eprint.iacr.org/2020/1261 MuSig2 paper]).
* The public key inputs are serialized using x-only (32 byte) instead of compressed (33 byte) serialization. The reason for this is that as x-only keys are becoming more common, the full key may not be available.
* The public nonces are serialized in compressed format (33 bytes). We accept the small overhead compared to x-only serialization to avoid complicating the specification.
* This specification supports signing for ''tweaked'' aggregate public keys. There are two modes of tweaking. ''Ordinary'' tweaking allows deriving child aggregate public keys per [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]. ''X-only'' tweaking allows creating a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] Taproot tweak. See section [[#tweaking|Tweaking]] below for details.
2021-01-12 14:21:20 +00:00
=== Notation ===
2021-01-12 14:21:20 +00:00
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<ref>Among other pitfalls, using the specification with a curve whose order is not close to the size of the range of the nonce derivation function is insecure.</ref>.
* Lowercase variables represent integers or byte arrays.
** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''.
** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''.
* Uppercase variables refer to points on the curve with equation ''y<sup>2</sup> = x<sup>3</sup> + 7'' over the integers modulo ''p''.
** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity.
** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity).
** The constant ''G'' refers to the base point, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''.
** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation].
** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation.
* Functions and operations:
** ''||'' refers to byte array concatenation.
** The function ''x[i:j]'', where ''x'' is a byte array and ''i, j &ge; 0'', returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''.
** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first.
** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''.
** The function ''has_even_y(P)'', where ''P'' is a point for which ''not is_infinite(P)'', returns ''y(P) mod 2 = 0''.
** The function ''with_even_y(P)'', where ''P'' is a point, returns ''P'' if ''is_infinite(P)'' or ''has_even_y(P)''. Otherwise, ''with_even_y(P)'' returns ''-P''.
** The function ''cbytes(P)'', where ''P'' is a point, returns ''a || bytes(P)'' where ''a'' is a byte that is ''2'' if ''has_even_y(P)'' and ''3'' otherwise.
** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''.
** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..2<sup>256</sup>-1'', returns the point ''P'' for which ''x(P) = x''<ref>
Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x<sup>3</sup> + 7 mod p'' and they can be computed as ''y = &plusmn;c<sup>(p+1)/4</sup> mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''.</ref> and ''has_even_y(P)'', or fails if ''x'' is greater than ''p-1'' or no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode:
*** Fail if ''x &gt; p-1''.
2021-01-12 14:21:20 +00:00
*** Let ''c = x<sup>3</sup> + 7 mod p''.
*** Let ''y' = c<sup>(p+1)/4</sup> mod p''.
*** Fail if ''c &ne; y'<sup>2</sup> mod p''.
*** Let ''y = y' '' if ''y' mod 2 = 0'', otherwise let ''y = p - y' ''.
*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''.
** The function ''point(x)'', where ''x'' is a 32-byte array ("x-only" serialization), returns ''lift_x(int(x))''. Fail if ''lift_x'' fails.
** The function ''pointc(x)'', where ''x'' is a 33-byte array (compressed serialization), sets ''P = lift_x(int(x[1:33]))'' and fails if that fails. If ''x[0] = 2'' it returns ''P'' and if ''x[0] = 3'' it returns ''-P''. Otherwise, it fails.
2021-01-12 14:21:20 +00:00
** The function ''hash<sub>tag</sub>(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''.
* Other:
** Tuples are written by listing the elements within parentheses and separated by commas. For example, ''(2, 3, 1)'' is a tuple.
2021-01-12 14:21:20 +00:00
=== Specification ===
2021-01-12 14:21:20 +00:00
==== Key Sorting ====
Input:
* The number ''u'' of public keys with ''0 < u < 2^32''
2021-01-12 14:21:20 +00:00
* The public keys ''pk<sub>1..u</sub>'': ''u'' 32-byte arrays
The algorithm '''''KeySort(pk<sub>1..u</sub>)''''' is defined as:
2021-01-12 14:21:20 +00:00
* Return ''pk<sub>1..u</sub>'' sorted in lexicographical order.
==== Key Aggregation ====
Input:
* The number ''u'' of public keys with ''0 < u < 2^32''
2021-01-12 14:21:20 +00:00
* The public keys ''pk<sub>1..u</sub>'': ''u'' 32-byte arrays
The algorithm '''''KeyAgg(pk<sub>1..u</sub>)''''' is defined as:
* Let ''Q = KeyAggInternal(pk<sub>1..u</sub>)''; fail if that fails.
* Return ''bytes(Q)''.
The algorithm '''''KeyAggInternal(pk<sub>1..u</sub>)''''' is defined as:
2021-01-12 14:21:20 +00:00
* For ''i = 1 .. u'':
** Let ''a<sub>i</sub> = KeyAggCoeff(pk<sub>1..u</sub>, pk<sub>i</sub>)''.
** Let ''P<sub>i</sub> = point(pk<sub>i</sub>)''; fail if that fails.
* Let ''Q = a<sub>1</sub>⋅P<sub>1</sub> + a<sub>2</sub>⋅P<sub>1</sub> + ... + a<sub>u</sub>⋅P<sub>u</sub>''
* Fail if ''is_infinite(Q)''.
* Return ''Q''.
2021-01-12 14:21:20 +00:00
The algorithm '''''HashKeys(pk<sub>1..u</sub>)''''' is defined as:
* Return ''hash<sub>KeyAgg list</sub>(pk<sub>1</sub> || pk<sub>2</sub> || ... || pk<sub>u</sub>)''
2021-01-12 14:21:20 +00:00
The algorithm '''''IsSecond(pk<sub>1..u</sub>, pk')''''' is defined as:
2021-01-12 14:21:20 +00:00
* For ''j = 1 .. u'':
** If ''pk<sub>j</sub> &ne; pk<sub>1</sub>'':
*** Return ''true'' if ''pk<sub>j</sub> = pk' '', otherwise return ''false''.
2021-01-12 14:21:20 +00:00
* Return ''false''
The algorithm '''''KeyAggCoeff(pk<sub>1..u</sub>, pk')''''' is defined as:
2021-01-12 14:21:20 +00:00
* Let ''L = HashKeys(pk<sub>1..u</sub>)''.
* If ''IsSecond(pk<sub>1..u</sub>, pk')'':
** Return 1
* Return ''int(hash<sub>KeyAgg coefficient</sub>(L || pk')) mod n''
2021-01-12 14:21:20 +00:00
==== Nonce Generation ====
The algorithm '''''NonceGen()''''' is defined as:
* Generate two random integers ''k<sub>1</sub>, k<sub>2</sub>'' in the range ''1...n-1''
* Let ''R<sup>*</sup><sub>1</sub> = k<sub>1</sub>⋅G, R<sup>*</sup><sub>2</sub> = k<sub>2</sub>⋅G''
* Let ''pubnonce = cbytes(R<sup>*</sup><sub>1</sub>) || cbytes(R<sup>*</sup><sub>2</sub>)''
* Let ''secnonce = bytes(k<sub>1</sub>) || bytes(k<sub>2</sub>)''
* Return ''secnonce'' and ''pubnonce''
==== Nonce Aggregation ====
* The number ''u'' of ''pubnonces'' with ''0 < u < 2^32''
* The public nonces ''pubnonce<sub>1..u</sub>'': ''u'' 66-byte arrays
The algorithm '''''NonceAgg(pubnonce<sub>1..u</sub>)''''' is defined as:
* For ''i = 1 .. 2'':
** For ''j = 1 .. u'':
*** Let ''R<sub>i,j</sub> = pointc(pubnonce<sub>j</sub>[(i-1)*33:i*33])''; fail if that fails
** Let ''R'<sub>i</sub> = R<sub>i,1</sub> + R<sub>i,2</sub> + ... + R<sub>i,u</sub>''
** <div id="NonceAgg infinity"></div>Let ''R<sub>i</sub> = R'<sub>i</sub>'' if not ''is_infinite(R'<sub>i</sub>)'', otherwise let R<sub>i</sub> = G'' (see [[#dealing-with-infinity-in-nonce-aggregation|Dealing with Infinity in Nonce Aggregation]])
* Return ''aggnonce = cbytes(R<sub>1</sub>) || cbytes(R<sub>2</sub>)''
==== Session Context ====
The Session Context is a data structure consisting of the following elements:
* The aggregate public nonce ''aggnonce'': a 66-byte array
* The number ''u'' of public keys with ''0 < u < 2^32''
* The public keys ''pk<sub>1..u</sub>'': ''u'' 32-byte arrays
* The message ''m'': a 32-byte array
We write "Let ''(aggnonce, u, pk<sub>1..u</sub>, m) = session_ctx''" to assign names to the elements of a Session Context.
The algorithm '''''GetSessionValues(session_ctx)''''' is defined as:
* Let ''(aggnonce, u, pk<sub>1..u</sub>, m) = session_ctx''
* Let ''Q = KeyAggInternal(pk<sub>1..u</sub>)''; fail if that fails
* Let ''b = int(hash<sub>MuSig/noncecoef</sub>(aggnonce || bytes(Q) || m)) mod n''
* Let ''R<sub>1</sub> = pointc(aggnonce[0:33]), R<sub>2</sub> = pointc(aggnonce[33:66])''; fail if that fails
* Let ''R = R<sub>1</sub> + b⋅R<sub>2</sub>''
* Fail if ''is_infinite(R)''
* Let ''e = int(hash<sub>BIP0340/challenge</sub>(bytes(R) || bytes(Q) || m)) mod n''
* Return ''(Q, b, R, e)''
The algorithm '''''GetSessionKeyAggCoeff(session_ctx, P)''''' is defined as:
* Let ''(_, u, pk<sub>1..u</sub>, _) = session_ctx''
* Return ''KeyAggCoeff(pk<sub>1..u</sub>, bytes(P))''
==== Signing ====
Input:
* The secret nonce ''secnonce'' that has never been used as input to ''Sign'' before: a 64-byte array
* The secret key ''sk'': a 32-byte array
* The ''session_ctx'': a [[#session-context|Session Context]] data structure
The algorithm '''''Sign(secnonce, sk, session_ctx)''''' is defined as:
* Let ''(Q, b, R, e) = GetSessionValues(session_ctx)''; fail if that fails
* Let ''k'<sub>1</sub> = int(secnonce[0:32]), k'<sub>2</sub> = int(secnonce[32:64])''
* Fail if ''k'<sub>i</sub> = 0'' or ''k'<sub>i</sub> &ge; n'' for ''i = 1..2''
* Let ''k<sub>1</sub> = k'<sub>1</sub>, k<sub>2</sub> = k'<sub>2</sub> '' if ''has_even_y(R)'', otherwise let ''k<sub>1</sub> = n - k'<sub>1</sub>, k<sub>2</sub> = n - k<sub>2</sub>''
* Let ''d' = int(sk)''
* Fail if ''d' = 0'' or ''d' &ge; n''
* Let ''P = d'⋅G''
* Let ''mu = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
* Let ''d = n - d' '' if ''has_even_y(P) `XOR` has_even_y(Q)'', otherwise let ''d = d' ''
* Let ''s = (k<sub>1</sub> + b⋅k<sub>2</sub> + e⋅mu⋅d) mod n''
* Let ''psig = bytes(s)''
* Let ''pubnonce = cbytes(k'<sub>1</sub>⋅G) || cbytes(k'<sub>2</sub>⋅G)''
* If ''PartialSigVerifyInternal(psig, pubnonce, bytes(P), session_ctx)'' (see below) returns failure, abort<ref>Verifying the signature before leaving the signer prevents random or attacker provoked computation errors. This prevents publishing invalid signatures which may leak information about the secret key. It is recommended, but can be omitted if the computation cost is prohibitive.</ref>.
* Return partial signature ''psig''
==== Partial Signature Verification ====
Input:
* The partial signature ''psig'': a 32-byte array
* The number ''u'' of public nonces and public keys with ''0 < u < 2^32''
* The public nonces ''pubnonce<sub>1..u</sub>'': ''u'' 66-byte arrays
* The public keys ''pk<sub>1..u</sub>'': ''u'' 32-byte arrays
* The message ''m'': a 32-byte array
* The index of the signer ''i'' in the public nonces and public keys with ''0 < i &le; u''
The algorithm '''''PartialSigVerify(psig, pubnonce<sub>1..u</sub>, pk<sub>1..u</sub>, m, i)''''' is defined as:
* Let ''aggnonce = NonceAgg(pubnonce<sub>1..u</sub>)''; fail if that fails
* Let ''session_ctx = (aggnonce, u, pk<sub>1..u</sub>, m)''
* Run ''PartialSigVerifyInternal(psig, pubnonce<sub>i</sub>, pk<sub>i</sub>, session_ctx)''
* Return success iff no failure occurred before reaching this point.
===== PartialSigVerifyInternal =====
Input:
* The partial signature ''psig'': a 32-byte array
* The public nonce of the signer ''pubnonce'': a 66-byte array
* The public key of the signer ''pk<sup>*</sup>'' (in ''pk<sub>1..u</sub>'' of the session_ctx''): a 32-byte array
* The ''session_ctx'': a [[#session-context|Session Context]] data structure
The algorithm '''''PartialSigVerifyInternal(psig, pubnonce, pk<sup>*</sup>, session_ctx)''''' is defined as:
* Let ''(Q, b, R, e) = GetSessionValues(session_ctx)''; fail if that fails
* Let ''s = int(psig)''; fail if ''s &ge; n''
* Let ''R<sup>*</sup><sub>1</sub> = pointc(pubnonce[0:33]), R<sup>*</sup><sub>2</sub> = pointc(pubnonce[33:66])''
* Let ''R<sup>*</sup>' = R<sup>*</sup><sub>1</sub> + b⋅R<sup>*</sup><sub>2</sub>''
* Let ''R<sup>*</sup> = R<sup>*</sup>' '' if ''has_even_y(R)'', otherwise let ''R<sup>*</sup> = -R<sup>*</sup>' ''
* Let ''P' = point(pk<sup>*</sup>)''; fail if that fails
* Let ''P = P' '' if ''has_even_y(Q)'', otherwise let ''P = -P' ''
* Let ''mu = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
* Fail if ''s⋅G &ne; R<sup>*</sup> + e⋅mu⋅P''
* Return success iff no failure occurred before reaching this point.
==== Partial Signature Aggregation ====
Input:
* The number ''u'' of signatures with ''0 < u < 2^32''
* The partial signatures ''psig<sub>1..u</sub>'': ''u'' 32-byte arrays
* The ''session_ctx'': a [[#session-context|Session Context]] data structure
The algorithm '''''PartialSigAgg(psig<sub>1..u</sub>, session_ctx)''''' is defined as:
* Let ''(_, _, R, _) = GetSessionValues(session_ctx)''; fail if that fails
* For ''i = 1 .. u'':
** Let ''s<sub>i</sub> = int(psig<sub>i</sub>)''; fail if ''s<sub>i</sub> &ge; n''.
* Let ''s = s<sub>1</sub> + ... + s<sub>u</sub> mod n''
* Return ''sig = ''bytes(R) || bytes(s)''
=== Signing Flow ===
Note that this specification unnecessarily recomputes intermediary values (such as the aggregate 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>''.
=== Remarks on Security and Correctness ===
==== Tweaking ====
This MuSig specification supports two modes of tweaking that correspond to the following algorithms:
Input:
* ''P'': a point
* The tweak ''t'': an integer with ''0 &le; t < n ''
The algorithm '''''OrdinaryTweak(P, t)''''' is defined as:
* Return ''P + t⋅G''
The algorithm '''''XonlyTweak(P, t)''''' is defined as:
* Return ''with_even_y(P) + t⋅G''
==== Dealing with Infinity in Nonce Aggregation ====
If it happens that ''is_infinite(R'<sub>i</sub>)'' inside ''[[#NonceAgg infinity|NonceAgg]]'' there is at least one dishonest signer (except with negligible probability).
If we fail here, we will never be able to determine who it is.
Therefore, we continue so that the culprit is revealed when collecting and verifying partial signatures.
However, dealing with the point at infinity requires defining a serialization and may require extra code complexity in implementations.
Instead of incurring this complexity, we make two modifications (compared to the MuSig2* appendix in the [https://eprint.iacr.org/2020/1261 MuSig2 paper]) to avoid infinity while still allowing us to detect the dishonest signer:
* In ''NonceAgg'', if an output ''R'<sub>i</sub>'' would be infinity, instead output the generator (an arbitrary choice).
* In ''Sign'', implicitly disallow the input ''aggnonce'' to contain infinity (since the serialization format doesn't support it).
The entire ''NonceAgg'' function (both the original and modified version) only depends on publicly available data (the set of public pre-nonces from every signer).
In the unforgeability proof, ''NonceAgg'' is considered to be performed by an untrusted party; thus modifications to ''NonceAgg'' do not affect the unforgeability of the scheme.
The (implicit) modification to ''Sign'' is equivalent to adding a clause, "abort if the input ''aggnonce'' contained infinity".
This modification only depends on the publicly available ''aggnonce''.
Given a successful adversary against the security game (EUF-CMA) for the modified scheme, a reduction can win the security game for the original scheme by simulating the modification (i.e. checking whether to abort) towards the adversary.
We conclude that these two modifications preserve the security of the MuSig2* scheme.
2021-01-12 14:21:20 +00:00
== Applications ==
== 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.
2021-01-12 14:21:20 +00:00
== Footnotes ==
<references />
== Acknowledgements ==