
Abstract: BIP-327 defines an interoperable specification of MuSig2, an aggregated multisig scheme over secp256k1, in which multiple participants collaborate to produce a single regular BIP340 signature. The resulting signature is verified as the signature of a single x-only public key, making MuSig2 particularly relevant for Taproot: cooperative n-of-n spends are indistinguishable on-chain from single-owner spends.
Keywords: Bitcoin, BIP-327, MuSig2, Schnorr, BIP340, Taproot, secp256k1, nonce, key aggregation, partial signature, AOMDL, cryptanalysis.
1. Status and scope of the norm
BIP-327 has an Active status , an Informational type , and describes MuSig2*, an optimized variant of MuSig2 for compatibility with BIP340 keys and signatures. Despite its informational type, it is a normative interface and algorithmic contract for wallets, hardware signers, coordinators, and libraries that must create mutually compatible signatures.
The scheme is an n-of-n , not a t-of-n, threshold scheme: all keys included in the aggregation must participate in a given session. Therefore, MuSig2 cannot be used interchangeably with the term “threshold signature”: the failure of even one participant halts cooperative signing, although BIP-327 introduces mechanisms for identifiable interruption.
2. Cryptographic model
The work is carried out in a group of points of the elliptic curve secp256k1: 0 3c( 53 3d), where 53 is the order of the base point G. The points satisfy the equation of the curve, and the private secret d and the public key P are related by the equality:
P = d · G, E: y^2 = x^3 + 7 (mod p), p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F, n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141.
BIP340 uses an x-only representation: a 32-byte x-coordinate is taken from a point, and canonicity is ensured by choosing a point with an even y-coordinate. KeyAgg inputs in BIP-327, by contrast, are ordinary compressed 33-byte public keys; this is important for accurately linking a signer to their private key.
3. Key aggregation
During the setup phase, participants transmit public keys pk_i = cbytes(P_i). To mitigate rogue-key attacks, each key receives a coefficient based on the full list of keys; a simple addition P_1 + … + P_u would be an insecure construction in an open key registration model.
L = H_tag(“KeyAgg list”, pk_1 || … || pk_u) a_i = 1 if pk_i = pk_2; otherwise int(H_tag(“KeyAgg coefficient”, L || pk_i)) mod n Q = Σ(i=1..u) a_i · P_i.
The MuSig2* optimization assigns a coefficient of 1 to the second distinct key of a list, preserving provable security and saving one dot multiplication operation. The order of the keys affects Q; if the application protocol does not specify a canonical order, BIP-327 defines a lexicographic order KeySort.
# Псевдокод KeyAgg
keys = KeySort([pk_alice, pk_bob]) # только если протокол требует сортировку
L = tagged_hash("KeyAgg list", concat(keys))
pk2 = first_key_different_from(keys[0])
a = [1 if pk == pk2 else H_scalar("KeyAgg coefficient", L + pk) for pk in keys]
Q = sum(ai * decode_compressed(pk) for ai, pk in zip(a, keys))
assert Q != INFINITY
A historical cryptanalytic example. The rogue-key attack is known for naive public key aggregation: an attacker could choose their key as P_M = X – P_A, so that the aggregate equals X, whose secret they know, and then simulate a shared signature without knowing Alice’s secret. The coefficients hashing the entire key set make such adaptive “subtraction” computationally impractical: the attacker would have to solve a self-consistent hash dependency.
4. Two-round protocol
| Round | Signer’s action | Aggregator/peer action | Result |
|---|---|---|---|
| 1. Nonce | Runs NonceGen, saves locally secnonce, sends 66-byte pubnonce. | Collects public nonces, executes NonceAgg, sends aggnonce. | A generic nonce with two components. |
| 2. Partial signature | Calculates psig_i = Sign(secnonce_i, sk_i, session_ctx). | If necessary, checks PartialSigVerify, then sums PartialSigAgg. | One 64-byte BIP340 signature. |
The aggregator is untrusted to maintain unfalsifability: it can disrupt a session, spoof a route, or create a mismatch, but it must not be able to forge a signature if at least one honest signatory is present. Identifying the culprit requires authenticated channels, honest nonce aggregation, and verification of each partial signature.
5. Nonce management
Each signer creates two scalar nonce values, k_1 and k_2, and publishes the corresponding points. These two components allow the nonce to be associated with a specific session and form the basis of the two-round MuSig2 design.
R_i* = (R_i,1*, R_i,2*) = (k_i,1·G, k_i,2·G) pubnonce_i = cbytes(R_i,1*) || cbytes(R_i,2*) R_j = Σ_i R_i,j, j ∈ {1,2} b = int(H_tag(“MuSig/noncecoef”, aggnonce || x(Q) || m)) mod n R’ = R_1 + b·R_2.
Then R = R’ (or G if R’ is infinity) is chosen; for odd y-coordinate R, the nonce scalars in the signature are inverted modulo n. Binding b to aggnonce, the aggregated key, and the message prevents an attacker from reusing observed nonces in another session without changing the computational context.
Critical rule: The same nonce secnonce cannot be passed Sign twice. Two partial signatures with the same effective nonce and different calls yield linear equations with respect to the secret scalar; this is a direct, catastrophic key leak. The implementation must atomically mark the nonce as used and reliably erase it, for example, by overwriting 64 bytes with zeros.
# Жизненный паттерн для аппаратного подписанта
secnonce, pubnonce = NonceGen(sk, pk, aggpk, message, session_id)
persist_atomically(session_id, secnonce, state="reserved")
send_to_coordinator(pubnonce)
# После получения aggnonce:
psig = Sign(secnonce, sk, session_ctx)
secure_erase(secnonce)
mark_used(session_id) # запрет любого повторного Sign
Cryptanalytic precedent. Nonce repetition is a classic source of compromise for ECDSA and Schnorr signatures. The most well-known practical class of incidents involves errors in random number generators and k repetition; in Bitcoin, this has historically manifested itself in vulnerable wallets, while in other ecosystems, nonce repetition has led to the recovery of private keys from signature pairs. In MuSig2, the risk is shifted to the level of each participant: their partial key can be leaked even if the other signers are correct.
6. Nonce generation and protection
NonceGen must receive fresh uniform 32 bytes from a high-quality CSPRNG. Secret nonces are derived by a tagged hash from randomness, an optional secret key, a private key, an aggregate key, a message, and additional context; BIP-327 recommends transmitting already available sk, aggpk, m and unique extra_in.
rand = sk XOR H_tag(«MuSig/aux», rand’) (if sk is given) k_i = int(H_tag(«MuSig/nonce», rand || len(pk) || pk || len(aggpk) || aggpk || m_prefixed || len(extra_in) || extra_in || (i-1))) mod n.
These inputs are a defense-in-depth measure, not a replacement for entropy: they reduce the risk of a nonce matching under a flaw rand'only if at least one associated parameter differs. Pre-generating a nonce before committing a message speeds up the protocol, but prolongs the storage time of the dangerous state and weakens this protection.
7. Partial signatures
The session context records the aggregated nonce, the complete ordered list of keys, the chain of tweaks, their modes, and the message. This is crucial: the signature should be associated not with an informal “intent to pay,” but with a precise serialization of the transaction message and a precise set of parameters.
e = int(H_tag(“BIP0340/challenge”, x(R) || x(Q) || m)) mod n d_i = g gacc d_i’ mod n s_i = k_i,1 + b k_i,2 + e a_i d_i mod n.
Here gacc , Q accumulates sign changes from previous x-only tweaks, and g normalizes the resulting Q to the x-only representation. This seemingly technical sign correction is necessary so that the sum of the partial signatures corresponds to the same point that the BIP340 verifier recovers from the x-only key.
# Проверка вклада i, выполняемая до агрегации
# s_i*G должно совпасть с эффективным nonce плюс ключевой член
assert s_i * G == R_eff_i + e * a_i * g_prime * P_i
# При успехе для всех i итоговая подпись корректна
Cryptanalytic meaning. A partial signature is not a signature in itself and can be forged without knowledge of the declared secret key. Its verification is not needed to verify the payment by a third party, but to isolate the incorrect participant: if all partial signatures pass the specified equality, the final aggregation will yield a verifiable BIP340 signature.
8. Final aggregation
After verifying the contributions, the aggregator sums the scalars and adds the accumulated tweak. The final signature is in standard BIP340 form and is verified by a standard BIP340 verifier without knowledge of the number of participants, their keys, or MuSig2 protocol messages.
s = Σ(i=1..u) s_i + e·g·tacc mod n sig = x(R) || bytes(32, s).
This compactness reduces the space and cost of verification compared to the n-of-n policy via OP_CHECKSIGADD, where individual keys and signatures are revealed. However, this gain comes at the cost of interactivity, nonce discipline, and accessibility of all participants.
9. Tweak and Taproot
BIP-327 supports two modes: plain tweak for unprotected BIP32 derivatives of the aggregate key and x-only tweak for BIP341 Taproot. For x-only tweak, the source point is first resigned, if necessary, to match the canonical representation.
Q’ = g·Q + t·G, g = -1 mod n, if is_xonally_t and y(Q) is odd; otherwise g = 1. tacc’ = t + g·tacc mod n, gacc’ = g·gacc mod n.
A taproot output with a MuSig2-aggregated internal key can simultaneously have a hidden script path. When cooperatively spending a key-path, an observer sees the standard signature; when using a script path, the script and control block are revealed, including the parity bit of the tweaked x-only key.
10. Identifiable abortion
MuSig2 doesn’t guarantee termination in the presence of an active adversary: a participant or coordinator may simply stop responding. However, with authenticated deposit delivery, honest nonce aggregation, and startup, PartialSigVerify an algorithm error indicates the index of a specific malicious signer.
In practice, this means logging the received hashes pubnonce, the full session context, and partial signatures, but not the secret nonce or keys. If the coordinator is untrusted, each signer must independently recalculate the aggregated nonce and key context; otherwise, the coordinator could create a false accusation or break the session representation.
11. Security boundaries
| Property | What does it provide? | What it doesn’t provide |
|---|---|---|
| KeyAgg Odds | Protection against naive rogue-key attacks. | Confirming the identity of the key owner. |
| Two rounds | Lower latency than three-round MuSig1. | Fault tolerance with offline signer. |
| Aggregator | Linear, not quadratic communication. | Guarantee of accessibility and honest behavior. |
| PartialSigVerify | Diagnosis of dishonest contribution. | Independent proof of psig as a signature. |
| Tagged SHA-256 | Hash domain separation. | Protection against secnonce memory leaks. |
The MuSig2 proof relies on the algebraic one-more discrete logarithm (AOMDL) assumption, not just the familiar discrete logarithm complexity. For an engineer, this doesn’t eliminate operational threats: the BIP-327 attack model assumes correct protocol execution, secure state storage, reliable entropy, and session context integrity.
12. Recommendations for implementation
- Use the proven constant-time library secp256k1; the provided pseudocode and BIP Python reference code are for understanding and testing purposes, not for production.
- Capture the binary serialization of keys, participant order, message, tweaks, and session ID before issuing a partial signature.
- Transmit and verify individual public keys in compressed 33-byte format; do not mix them with BIP340 x-only keys.
- Implement a one-time state machine for
secnonce: created, reserved, used/erased; failover after process failure should not be possible. - If the coordinator is untrusted, perform
NonceAggand verify partial signatures yourself, and sign or authenticate the transport. - Run official BIP-327 JSON test vectors, including negative cases, duplicate keys, infinity nonces, and tweak chains.
Conclusion
BIP-327 transforms multi-stakeholder control of a Bitcoin output into a single BIP340 signature, preserving the compactness and privacy of Taproot’s keypath. Its cryptanalytically most important condition is not mathematical exotica, but flawless management of one-time nonces: a violation of this invariant converts the secure scheme into a system of linear equations from which the secret key is derived.
Sources
BIP-327: MuSig2 and BIP340-compatible Schnorr signatures: https://autodd.ru/bip-327-musig2-and-bip340-compatible-schnorr-signatures/
- Bitcoin Improvement Proposal 327, MuSig2 for BIP340-Compatible Multi-Signatures , status Active, repository bitcoin/bips. https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki
- BIP-340, Schnorr Signatures for secp256k1 . https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
- BIP-341, Taproot: SegWit version 1 spending rules . https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
