BIP: ? Title: MuSig2 Author: Status: Draft License: BSD-3-Clause Type: Informational Created: 2022-03-22
This document proposes a standard for the MuSig2 protocol. The standard is compatible with BIP340 public keys and signatures. It also supports tweaking, which allows creating BIP341 Taproot outputs with key and script paths.
This document is licensed under the 3-clause BSD license.
MuSig2 is a multi-signature scheme that allows multiple signers to create a single aggregate public key and cooperatively create a single Schnorr signature for the aggregate key and a message. This is more space-efficient and has lower verification costs than each signer providing an individual public key and signature. Since MuSig2 is not a threshold-signature scheme, the cooperation of all signers involved in key aggregation is required to produce a signature.
One of the primary motivations for MuSig2 is the activation of Taproot (BIP341) on the Bitcoin network, which introduced the ability to authorize transactions with Schnorr signatures. This standard allows the creation of aggregate public keys that can be used in Taproot outputs. Such outputs are indistinguishable for a blockchain observer from regular, single-signer outputs but are actually controlled by multiple signers. Moreover, by tweaking an aggregate key, the shared Taproot output can have script spending paths that are hidden unless used.
There are multi-signature schemes other than MuSig2 that are fully compatible with Schnorr signatures. MuSig2 stands out by combining the following features:
- Simple Key Setup: Key aggregation is non-interactive and fully compatible with BIP340 public keys.
- Two Communication Rounds: MuSig2 is faster in practice than three-round multi-signature protocols, particularly when signers are connected through high-latency anonymizing links. Moreover, less communication rounds simplifies the specification and reduces the probability that users make security-relevant mistakes. To prove the security of using only two communication rounds, MuSig2 relies on the algebraic one-more discrete logarithm (AOMDL) assumption instead of the discrete logarithm assumption. AOMDL is a falsifiable and weaker variant of the well-studied OMDL problem.
- Low complexity: MuSig2 has a substantially lower computational and implementation complexity than alternative schemes like MuSig-DN. However, this comes at the cost of having no ability to generate nonces deterministically and the requirement to securely handle signing state.
- Compatibility with BIP340: The aggregate public key created as part of this MuSig2 specification is a BIP340 X-only public key, and the signature output at the end of the protocol is a BIP340 signature that passes BIP340 verification for the aggregate key and a message. The public keys that are input to the key aggregation algorithm are also X-only public keys. Compared to compressed serialization, this adds complexity to the specification, but as X-only keys are becoming more common, the full key may not be available.
- Tweaking for BIP32 derivations and Taproot: The specification supports tweaking aggregate public keys and signing for tweaked aggregate public keys. We distinguish two modes of tweaking: Ordinary tweaking can be used to derive child aggregate public keys per BIP32. X-only tweaking, on the other hand, allows creating a BIP341 tweak to add script paths to a Taproot output. See section Tweaking below for details.
- 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.
- 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 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 MuSig2 paper gives distinct security proofs depending on the number of points that constitute a nonce. See section Choosing the Size of the Nonce for a discussion.
When implementing the specification, make sure to understand this section thoroughly, particularly the Signing Flow, to avoid subtle mistakes that lead to catastrophic failure.
The following conventions are used, with constants as defined for secp256k1. We note that adapting this specification to other elliptic curves is not straightforward and can result in an insecure scheme.
- 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 y2 = x3 + 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 elliptic curve group operation.
- 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 ≥ 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..2256-1, returns the point P for which x(P) = x[1] 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 > p-1.
- Let c = x3 + 7 mod p.
- Let y' = c(p+1)/4 mod p.
- Fail if c ≠ y'2 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.
- The function hashtag(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.
Input:
- The number u of public keys with 0 < u < 2^32
- The public keys pk1..u: u 32-byte arrays
- Return pk1..u sorted in lexicographical order.
Input:
- The number u of public keys with 0 < u < 2^32
- The public keys pk1..u: u 32-byte arrays
- The number v of tweaks with 0 ≤ v < 2^32
- The tweaks tweak1..v: v 32-byte arrays
- The tweak methods is_xonly_t1..v : v booleans
- Let (Q,_,_) = KeyAggInternal(pk1..u, tweak1..v, is_xonly_t1..v); fail if that fails.
- Return bytes(Q).
- Let pk2 = GetSecondKey(pk1..u)
- For i = 1 .. u:
- Let Pi = point(pki); fail if that fails.
- Let ai = KeyAggCoeff'(pk1..u, pki, pk2).
- Let Q0 = a1⋅P1 + a2⋅P1 + ... + au⋅Pu
- Fail if is_infinite(Q0).
- Let tacc0 = 0
- Let gacc0 = 1
- For i = 1 .. v:
- Let (Qi, gacci, tacci) = Tweak(Qi-1, gacci-1, tweaki, tacci-1, is_xonly_ti); fail if that fails
- Return (Qv, gaccv, taccv).
- Return hashKeyAgg list(pk1 || pk2 || ... || pku)
- For j = 1 .. u:
- If pkj ≠ pk1:
- Return pkj
- If pkj ≠ pk1:
- Return bytes(0)
- Let pk2 = GetSecondKey(pk1..u):
- Return KeyAggCoeff'(pk1..u, pk', pk2)
- Let L = HashKeys(pk1..u)
- If pk' = pk2:
- Return 1
- Return int(hashKeyAgg coefficient(L || pk')) mod n
- If is_xonly_ti and not has_even_y(Qi-1):
- Let gi-1 = -1 mod n
- Else: let gi-1 = 1
- Let ti = int(tweaki); fail if t ≥ n
- Let Qi = gi-1⋅Qi-1 + ti⋅G
- Fail if is_infinite(Qi)
- Let gacci = gi-1⋅gacci-1 mod n
- Let tacci = ti + gi-1⋅tacci-1 mod n
- Return (Qi, gacci, tacci)
NonceGen():
- Generate two random integers k1, k2 in the range 1...n-1
- Let R*1 = k1⋅G, R*2 = k2⋅G
- Let pubnonce = cbytes(R*1) || cbytes(R*2)
- Let secnonce = bytes(k1) || bytes(k2)
- Return secnonce and pubnonce
Input:
- The number u of pubnonces with 0 < u < 2^32
- The public nonces pubnonce1..u: u 66-byte arrays
- For i = 1 .. 2:
- For j = 1 .. u:
- Let Ri,j = pointc(pubnoncej[(i-1)*33:i*33]); fail if that fails
- Let R'i = Ri,1 + Ri,2 + ... + Ri,u
- Let Ri = R'i if not is_infinite(R'i), otherwise let Ri = G (see Dealing with Infinity in Nonce Aggregation)
- For j = 1 .. u:
- Return aggnonce = cbytes(R1) || cbytes(R2)
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 pk1..u: u 32-byte arrays
- The number v of tweaks with 0 ≤ v < 2^32
- The tweaks tweak1..v: v 32-byte arrays
- The tweak methods is_xonly_t1..v : v booleans
- The message m: a 32-byte array
GetSessionValues(session_ctx):
- Let (aggnonce, u, pk1..u, v, tweak1..v, is_xonly_t1..v, m) = session_ctx
- Let (Q, gaccv, taccv) = KeyAggInternal(pk1..u, tweak1..v, is_xonly_t1..v); fail if that fails
- Let b = int(hashMuSig/noncecoef(aggnonce || bytes(Q) || m)) mod n
- Let R1 = pointc(aggnonce[0:33]), R2 = pointc(aggnonce[33:66]); fail if that fails
- Let R = R1 + b⋅R2
- Fail if is_infinite(R)
- Let e = int(hashBIP0340/challenge(bytes(R) || bytes(Q) || m)) mod n
- Return (Q, gaccv, taccv, b, R, e)
- Let (_, u, pk1..u, _, _, _, _) = session_ctx
- Return KeyAggCoeff(pk1..u, bytes(P))
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 data structure
- Let (Q, gaccv, _, b, R, e) = GetSessionValues(session_ctx); fail if that fails
- Let k'1 = int(secnonce[0:32]), k'2 = int(secnonce[32:64])
- Fail if k'i = 0 or k'i ≥ n for i = 1..2
- Let k1 = k'1, k2 = k'2 if has_even_y(R), otherwise let k1 = n - k'1, k2 = n - k2
- Let d' = int(sk)
- Fail if d' = 0 or d' ≥ n
- Let P = d'⋅G
- Let a = GetSessionKeyAggCoeff(session_ctx, P); fail if that fails
- Let gp = 1 if has_even_y(P), otherwise let gp = -1 mod n
- Let gv = 1 if has_even_y(Q), otherwise let gv = -1 mod n
- Let d = gv⋅gaccv⋅gp⋅d' (See Negation Of The Secret Key When Signing)
- Let s = (k1 + b⋅k2 + e⋅a⋅d) mod n
- Let psig = bytes(s)
- Let pubnonce = cbytes(k'1⋅G) || cbytes(k'2⋅G)
- If PartialSigVerifyInternal(psig, pubnonce, bytes(P), session_ctx) (see below) returns failure, abort[2].
- Return partial signature psig
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 pubnonce1..u: u 66-byte arrays
- The public keys pk1..u: u 32-byte arrays
- The number v of tweaks with 0 ≤ v < 2^32
- The tweaks tweak1..v: v 32-byte arrays
- The tweak methods is_xonly_t1..v : v booleans
- The message m: a 32-byte array
- The index of the signer i in the public nonces and public keys with 0 < i ≤ u
- Let aggnonce = NonceAgg(pubnonce1..u); fail if that fails
- Let session_ctx = (aggnonce, u, pk1..u, v, tweak1..v, is_xonly_t1..v, m)
- Run PartialSigVerifyInternal(psig, pubnoncei, pki, session_ctx)
- Return success iff no failure occurred before reaching this point.
- 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* (in pk1..u of the session_ctx): a 32-byte array
- The session_ctx: a Session Context data structure
- Let (Q, gaccv, _, b, R, e) = GetSessionValues(session_ctx); fail if that fails
- Let s = int(psig); fail if s ≥ n
- Let R*1 = pointc(pubnonce[0:33]), R*2 = pointc(pubnonce[33:66])
- Let R*' = R*1 + b⋅R*2
- Let R* = R*' if has_even_y(R), otherwise let R* = -R*'
- Let gv = 1 if has_even_y(Q), otherwise let gv = -1 mod n
- Let g' = gv⋅gaccv mod n
- Let P = g'⋅point(pk*); fail if that fails (See Negation Of The Public Key When Partially Verifying)
- Let a = GetSessionKeyAggCoeff(session_ctx, P); fail if that fails
- Fail if s⋅G ≠ R* + e⋅a⋅P
- Return success iff no failure occurred before reaching this point.
Input:
- The number u of signatures with 0 < u < 2^32
- The partial signatures psig1..u: u 32-byte arrays
- The session_ctx: a Session Context data structure
- Let (Q, _, taccv, _, _, R, e) = GetSessionValues(session_ctx); fail if that fails
- For i = 1 .. u:
- Let si = int(psigi); fail if si ≥ n.
- Let gv = 1 if has_even_y(Q), otherwise let gv = -1 mod n
- Let s = s1 + ... + su + e⋅gv⋅taccv mod n
- Return sig = bytes(R) || bytes(s)
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 k1 and k2.
There are some vectors in libsecp256k1's MuSig test file. Search for the musig_test_vectors_keyagg and musig_test_vectors_sign functions.
This MuSig2 specification supports two modes of tweaking that correspond to the following algorithms:
Input:
- P: a point
- The tweak t: an integer with 0 ≤ t < n
- Return P + t⋅G
- Return with_even_y(P) + t⋅G
In order to produce a partial signature for an X-only public key that is an aggregate of u X-only keys and tweaked v times (X-only or ordinarily), the Sign algorithm may need to negate the secret key during the signing process.
• Pi as computed in KeyAggInternal is the point corresponding to the i-th signer's X-only public key. Defining d'i to be the d' value as computed in the Sign algorithm of the i-th signer, we have
Pi = with_even_y(d'i⋅G) .
• Q0 is an aggregate of the signer's public keys and defined in KeyAggInternal as
Q0 = a1⋅P1 + a2⋅P1 + ... + au⋅Pu.
• Qi as computed in Tweak for 1 ≤ i ≤ v is the tweaked public key after the i-th tweaking operation. It holds that
Qi = f(i-1) + ti⋅G for i = 1, ..., v where
f(i) := with_even_y(Qi) if is_xonly_ti+1 and
f(i) := Qi otherwise.
The goal is to produce a partial signature corresponding to the output of KeyAgg, i.e., the final (X-only) public key point after v tweaking operations with_even_y(Qv).
Pi = gpi⋅d'i⋅G.
For 0 ≤ i ≤ v-1, the Tweak algorithm called from KeyAggInternal sets gi to -1 mod n if and only if is_xonly_ti+1 is true and Qi has an odd Y coordinate. Therefore, we have
f(i) = gi⋅Qi for 0 ≤ i ≤ v - 1.
Furthermore, the Sign and PartialSigVerify algorithms set gv such that
with_even_y(Qv) = gv⋅Qv.
with_even_y(Qv)
= gv⋅Qv
= gv⋅(f(v-1) + tv⋅G)
= gv⋅(gv-1⋅(f(v-2) + tv-1⋅G) + tv⋅G)
= gv⋅gv-1⋅f(v-2) + gv⋅(tv + gv-1⋅tv-1)⋅G
= gv⋅gv-1⋅f(v-2) + (sumi=v-1..v ti⋅prodj=i..v gj)⋅G
= gv⋅gv-1⋅...⋅g1⋅f(0) + (sumi=1..v ti⋅prodj=i..v gj)⋅G
= gv⋅...⋅g0⋅Q0 + gv⋅taccv⋅G
where tacci is computed by KeyAggInternal and Tweak as follows:
tacc0 = 0
tacci = ti + gi-1⋅tacci-1 for i=1..v mod n
for which it holds that gv⋅taccv = sumi=1..v ti⋅prodj=i..v gj.
gacc0 = 1
gacci = gi-1⋅gacci-1 for i=1..v mod n
So we can rewrite above equation for the final public key as
with_even_y(Qv) = gv⋅gaccv⋅Q0 + gv⋅taccv⋅G.
with_even_y(Qv) - gv⋅taccv⋅G
= gv⋅gaccv⋅Q0
= gv⋅gaccv⋅(a1⋅P1 + ... + au⋅Pu)
= gv⋅gaccv⋅(a1⋅gp1⋅d'1⋅G + ... + au⋅gpu⋅d'u⋅G)
= sumi=1..u(gv⋅gaccv⋅gpi⋅ai⋅d'i)*G.
Thus, signer i multiplies its secret key d'i with gv⋅gaccv⋅gpi in the Sign algorithm.
d = gv⋅gaccv⋅gp⋅d' mod n
when producing a partial signature to ensure that the aggregate signature will correspond to an aggregate public key with even Y coordinate.
s⋅G = R* + e⋅a⋅d⋅G.
d⋅G
= gv⋅gaccv⋅gp⋅d'⋅G
= gv⋅gaccv⋅point(pk*)
If it happens that is_infinite(R'i) inside 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 MuSig2 paper) to avoid infinity while still allowing us to detect the dishonest signer:
- In NonceAgg, if an output R'i 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 (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.
The MuSig2 paper contains two security proofs that apply to different protocol variants. The first is for a variant where each signer's nonce consists of four elliptic curve points and uses the random oracle model (ROM). In the second variant, the signers' nonces consist of only two points. Its proof requires a stronger model, namely the combination of the ROM and the algebraic group model (AGM). Relying on the stronger model is a legitimate choice for the following reasons:
First, an approach widely taken is interpreting a Forking Lemma proof in the ROM merely as design justification and ignoring the loss of security due to the Forking Lemma. If one believes in this approach, then the ROM may not be the optimal model in the first place because some parts of the concrete security bound are arbitrarily ignored. One may just as well move to the ROM+AGM model, which produces bounds close to the best-known attacks, e.g., for Schnorr signatures.
Second, as of this writing, there is no instance of a serious protocol with a security proof in the AGM that is not secure in practice. There are, however, insecure toy schemes with AGM security proofs, but those explicitly violate the requirements of the AGM. Broken AGM proofs of toy schemes provide group elements to the adversary without declaring them as group element inputs. In contrast, in MuSig2, all group elements that arise in the protocol are known to the adversary and declared as group element inputs. A scheme very similar to MuSig2 and with two-point nonces was independently proven secure in the ROM and AGM by Alper and Burdges.
- ^ 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 = x3 + 7 mod p and they can be computed as y = ±c(p+1)/4 mod p (see Quadratic residue) if they exist, which can be checked by squaring and comparing with c.
- ^ 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.