MuSig2 (BIP327)
Quick refs: protocol.md, key-agg.md, attacks.md
MuSig2 is the standard Schnorr key-aggregation protocol for Bitcoin.
n parties hold separate private keys, jointly produce a single public
key Q and a single signature (R, s) indistinguishable from a
single-key Schnorr signature.
Replaces MuSig1 (3-round) and MuSig-DN with simpler 2-round + better security proofs.
BIP327 is Status: Deployed, spec version 1.0.4 (as of September 2026).
Properties
- Indistinguishable — observers cannot tell
Qwas aggregated. - Off-chain coordination — n-of-n in 2 rounds with no on-chain multisig.
- Provably secure in the Algorithmic One-More-Discrete-Log (AOMDL)
- Random Oracle Model.
- Fits Taproot key-path — cheapest spend; no script-path needed for cooperative case.
Two-round protocol summary
Round 1 — Nonce exchange
Each signer i:
- Generates two ephemeral nonces
(k_{i,1}, k_{i,2}). - Computes
(R_{i,1}, R_{i,2}) = (k_{i,1}*G, k_{i,2}*G). - Broadcasts
R_{i,1}, R_{i,2}to all other signers (66 bytes total).
Aggregator computes:
R_1 = sum(R_{i,1}),R_2 = sum(R_{i,2}).b = TaggedHash("MuSig/noncecoef", R_1 || R_2 || agg_pubkey || msg).R = R_1 + b*R_2.
Round 2 — Partial sig exchange
Each signer i:
- Computes their partial sig
s_iusingR, message, key-agg coefficienta_i, etc. - Broadcasts
s_i.
Aggregator: s = sum(s_i) mod n.
Final sig: (R.x, s) — 64 bytes, valid BIP340 sig under Q.
Key aggregation
Inputs: pubkeys P_1, ..., P_n (in agreed-upon order)
1. L = sorted(P_i) (canonical order, byte-lex)
2. a_i = TaggedHash("KeyAgg coefficient", L || P_i.x)
3. Q = sum(a_i * P_i)
If Q.y is odd, parity bit g_q = -1, otherwise g_q = +1. This
parity is tracked through signing.
The coefficients a_i defeat the rogue-key attack that MuSig1
patched but earlier schemes had: an attacker who could pick their
public key after seeing others' would otherwise control the sum.
Tweaks (Taproot integration)
After key aggregation, Taproot tweak applies:
Q_tweaked = Q + t*G where t = TaggedHash("TapTweak", Q.x || merkle_root)
Signing for Q_tweaked requires an extra adjustment in the partial
sig phase. BIP327 specifies "tweak context" maintaining the
accumulated tweak.
Pre-shared nonces (NonceGen variants)
NonceGendeterministic from secret + msg + extra_in.- "MuSig2 with non-determinism" requires careful aux entropy.
- Critical: nonces must NOT be reused across different signing sessions, even with different messages. State must be persisted carefully (e.g., in encrypted nonce wallet).
Use cases in Bitcoin
- Joint custody — 2 partners co-spend with single-sig appearance.
- Lightning — Taproot channels (BOLT update) replace OP_2 pubkey with MuSig2-aggregated key for channel funding output.
- DAO multisig with privacy — n directors sign as one.
- Vault hot/cold cooperative spend — cold key + hot key aggregated for everyday use.
- Coinjoin servers with k-anonymity → users + service jointly sign.
Descriptors, PSBTs and wallet integration
BIP327 covers only the signing math. Three companion BIPs (all by Ava Chow) carry MuSig2 into wallet software — statuses as of September 2026:
- BIP328 (Complete) — Derivation Scheme for MuSig2 Aggregate
Keys. Wraps a plain aggregate pubkey in a synthetic xpub:
depth 0, child number 0, fixed chaincode
868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965(SHA256 of the textMuSig2MuSig2MuSig2). Only unhardened derivation is possible — there is no aggregate private key. EachCKDpubstep'sI_Lenters the session context as a plain tweak (is_xonly_t = false), so every signer must recompute the derivation tweaks for the child key being signed for. - BIP390 (Draft, v0.2.0) — the
musig(KEY,KEY,...,KEY)descriptor key expression. Allowed only insidetr(),rawtr()orsp(), never nested in anothermusig(). Keys are sorted withKeySortafter all derivation and before aggregation, so the order written in the descriptor does not matter.musig(...)/NUM/.../*derives from the aggregate key per BIP328, and is legal only when every participant is an xpub (or derived from one) and no participant itself uses/*or/<NUM;NUM;...>. No hardened steps aftermusig(). - BIP373 (Complete) — MuSig2 PSBT Fields, carrying both rounds
through an otherwise ordinary PSBT workflow:
PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS(0x1a),PSBT_IN_MUSIG2_PUB_NONCE(0x1b),PSBT_IN_MUSIG2_PARTIAL_SIG(0x1c) andPSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS(0x08).
Bitcoin Core parses musig() descriptors and reads/writes the BIP373
PSBT fields from v30.0 (October 2025); descriptor support merged
in PR #31244 (2025-07-31). Core accepts musig() only inside tr()
— not rawtr() or sp() — per doc/descriptors.md (v31.1, July
2026).
Security caveats
- Concurrent sessions — naive per-signer parallel sessions enable
"Wagner-style" forge attacks. Solution in BIP327: nonce binding to
message (the
bcoefficient). - State persistence — nonces must be wiped after one use. Power loss between round 1 and round 2 → must restart with fresh nonces.
- Hardware wallet support — still thin as of September 2026. The
Ledger Bitcoin app has shipped
musig()key expressions since v2.4.0 (CHANGELOG 2025-03-07; GitHub release 2025-03-17): at most 5 keys permusig(), at most 8 parallel signing sessions (persistent state is scarce),musig()allowed inmulti_abut notsortedmulti_a, and onlymusig(...)/**ormusig(...)/<M;N>/*— participants must be aggregated without further per-key derivation. v2.5.1 (CHANGELOG 2026-09-09) fixedmusig()insidemulti_afragments. Coldcard is the opposite case: the Mk4 and Q1 board configs both setNGU_INCL_MUSIG = 0("Exclude unused optional libngu secp256k1 features to save firmware space"), so MuSig is compiled out of the firmware entirely (as of September 2026). Either way a coordinator that speaks BIP373 PSBTs is required.
Implementations
libsecp256k1(secp256k1_musig_*— no2in the prefix). Mainline since v0.6.0 (2024-11-04) and built by default (--enable-module-musigis[default=yes]); not experimental.secp256k1_musig_keyagg_cacheandsecp256k1_musig_sessionstill have no serialization/parsing functions as of v0.8.0 (2026-08-03), so signing state cannot be persisted across a process restart between round 1 and round 2.rust-secp256k1— the module ismusig, notmusig2(secp256k1::musig:KeyAggCache,SecretNonce/PublicNonce,AggregatedNonce,Session,PartialSignature,AggregatedSignature). Support was added in the 0.32 development series (CHANGELOG entry "0.32.0 - 2025-10-02", which also removed theSecp256k1context from the public API), but no stable 0.32.0 was ever published — the three0.32.0-beta.*crates are yanked. The first stable release carrying MuSig2 is 0.33.0 (2026-08-28); current stable is 0.33.1 (2026-08-29).- BDK has no MuSig2 support as of September 2026. The blocker is
rust-miniscript: PR #954 (Add BIP390musig()descriptor key expressions) is still open, sobdk_wallet3.1.0 (2026-06-14) cannot even parsetr(musig(...))— bdk-ffi pins that behaviour in a test literally namedcannotCreateMusigDescriptor.
Common bugs
- Forgetting to apply parity flips during partial-sig phase
(
g_qandg_bmust propagate). - Reusing nonces across two attempts of the same session → key leak.
- Missing key-aggregation coefficient
a_i→ produces a sig under a different aggregated pubkey.