协议演进 / BIP/比特币改进提案 / BIP-327
BIP-327
为 MuSig2 多签定标准,让多位签名者聚合出一个普通公钥,并合作产出单笔 BIP340 Schnorr 签名。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-327 |
|---|---|
| 标题 | MuSig2 for BIP340-compatible Multi-Signatures |
| 作者 | Jonas Nick <[email protected]>, Tim Ruffing <[email protected]>, Elliott Jin <[email protected]> |
| 指定日期 | 2022-03-22 |
| 讨论日期 | 2022-04-05 |
| 类型 | Informational(信息类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/327 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki |
二、放在哪一族
Schnorr 多签族,坐落在 Taproot 生态的正中央。原文没有给它标注 Layer 字段;按内容看,它规范的是钱包与签名设备如何协作产出签名,属于应用层面的签名协议标准,而不是共识规则。
它直接建立在以下文档之上:
BIP-340:secp256k1 的 Schnorr 签名,聚合公钥与最终签名都必须与它兼容、能通过它的验证
BIP-341:Taproot 花费规则,MuSig2 的首要应用就是共同控制 Taproot 输出的密钥路径
BIP-32:分层确定性钱包,聚合公钥的普通微调(plain tweaking)用于按 BIP-32 派生子密钥
BIP-342:Taproot 脚本验证,其中的 OP_CHECKSIGADD 是脚本层 n-of-n 多签的对照方案
后续文档中,BIP-328 专门规定如何从本篇的聚合公钥构造 BIP-32 扩展公钥做派生;BIP-373 则定义 MuSig2 在 PSBT 中的字段。读本篇是读懂这一串 MuSig2 配套标准的前提。
三、它要解决什么
3.1 多人共同控制一个 Taproot 输出,需要统一标准
多位签名者想共同控制一个 Taproot 输出时,该输出里放的应是众人公钥聚合出的单个公钥,花费时再由众人合作产出对该公钥有效的普通 Schnorr 签名。不同软件项目若各行其是,就无法互操作。本篇要为 MuSig2 这一方案定出统一、互通的标准。
3.2 相比脚本多签:更省、更私密
与用 OP_CHECKSIGADD 在脚本里逐个列公钥、逐个验签名的 n-of-n 做法相比,MuSig2 的链上足迹本质上只是一个 BIP-340 公钥,花费时也只需要一个合作产出的签名,因此更紧凑、验证成本更低;签名者人数 n 也不受共识规则限制。
隐私上,MuSig2 的 Taproot 输出对链上观察者而言与普通单签 Taproot 输出不可区分,观察者看不出背后其实是多位签名者;聚合公钥还可以再做微调,把脚本花费路径藏起来,不用时不暴露。
3.3 为什么选 MuSig2 这个变体
原文列出它同时具备的几项特征:密钥聚合非交互、与 BIP-340 公钥完全兼容,设置简单;只需两轮通信,比 MuSig1 等三轮方案在高延迟匿名链路上更快,轮次少也降低了实现与使用出错的概率;安全性在代数一次以上离散对数(AOMDL)假设下可证明不可伪造;计算与实现复杂度明显低于 MuSig-DN 等替代方案。代价是:随机数(nonce)不能确定性生成,且必须安全地保管签名状态。
需要先说清:MuSig2 是 n-of-n 多签,不是 t-of-n 门限签名——签名需要密钥聚合涉及的全体签名者参与。
四、规则本身
4.1 密钥聚合(KeyAgg)
各签名者的个人公钥以普通(plain)压缩格式(33 字节)作为输入。KeyAgg 为每个公钥算一个聚合系数(其中第二个不同公钥的系数取常数 1,这是 MuSig2* 优化),加权求和得到聚合公钥。聚合结果依赖输入顺序;应用若无固定顺序,可先用 KeySort 按字典序排序以保证结果与初始顺序无关。同一公钥允许出现多次,算法本身能正确处理,实现被建议不必为重复公钥做检查而徒增错误处理。
聚合的输出是 KeyAgg 上下文,可分别取出 X-only 聚合公钥(供 BIP-340 验证)或普通聚合公钥(供某些微调场景)。
4.2 微调(tweaking)
聚合公钥可被微调,分两种模式:普通微调用于按 BIP-32 从聚合公钥派生子聚合公钥;X-only 微调用于按 BIP-341 做 Taproot 微调、给输出附加脚本路径。签名算法会把微调正确计入部分签名。原文提醒:微调值应按其他规范由聚合公钥等信息派生而来,不应接受任意来源的微调值。
4.3 两轮签名流程
第一轮(广播随机数):每位签名者运行 NonceGen 产生秘密随机数 secnonce 与公开随机数 pubnonce,彼此广播 pubnonce,再用 NonceAgg 聚合成聚合随机数。每个签名者的随机数由两个椭圆曲线点组成。
第二轮(广播部分签名):每位签名者用私钥、secnonce 与会话上下文运行 Sign 产生部分签名,彼此广播后用 PartialSigAgg 汇总。若所有人诚实,最终结果就是一笔能通过 BIP-340 验证的签名。
两轮都可改用一个不受信任的第三方聚合者收集、汇总再广播,把通信复杂度从平方级降到线性;恶意聚合者最多让本次签名失败,无法伪造签名。
4.4 红线:secnonce 绝不能重用
Sign 绝不能用同一个 secnonce 执行两次,否则两份部分签名足以泄露私钥。实现可在 Sign 读取后把 secnonce 覆写为 64 字节零值,全零的 secnonce 对 Sign 无效。
与单签 BIP-340 不同,这里的随机数分量不得从会话参数确定性地派生,否则主动攻击者能诱使受害者重用随机数。NonceGen 必须接入高质量随机源;可选参数(私钥、聚合公钥、消息、附加输入)只是纵深防御。第一轮也可预处理:在消息或签名者集合未定之前先交换随机数,参数定齐后直接进入第二轮。
4.5 可识别的中止
若有人发送无效贡献导致会话中止,诚实方在满足条件(贡献未经篡改、随机数聚合诚实完成、各部分签名都经 PartialSigVerify 验证)时,能指认出恰好一名恶意签名者。这称为可识别中止(identifiable aborts)。原文同时提醒:部分签名本身不是签名,攻击者可以伪造部分签名;PartialSigVerify 的唯一目的就是实现可识别中止,不需要该性质时可以不用。
五、谁必须动
普通持币人:单签钱包用户无事可做。使用 MuSig2 多签钱包时,要理解它需要全体签名者在线协作完成两轮通信,少一人就签不出。
钱包开发者:按本篇实现 KeyAgg、NonceGen、NonceAgg、Sign、PartialSigAgg 等算法,严守随机数不重用、随机数必须真随机、签名状态安全保管等要求;部分功能(如微调、非 32 字节消息、指认捣乱者)可按场景选做,不支持的输入应直接让算法失败。原文附有纯 Python 参考实现与 JSON 测试向量,仅供演示,不可用于生产。
全节点与矿工:无事可做。链上看到的仍是普通 BIP-340 公钥与签名,按既有 Taproot 规则验证即可。
共识层:不修改任何共识规则。本篇是信息类标准,规范的是链下协作签名过程。
六、现在算不算数,以及一个常见误读
状态为 Deployed(已部署)。在这里它表示这份 MuSig2 标准已经定稿并被作为可实现、可互操作的标准发布,供钱包与签名软件按同一套算法实现;它不是共识升级,不存在区块高度激活一说。
常见误读:
“MuSig2 是门限签名,n 个人里凑够 t 个就能花钱。”
不对。原文开宗明义:MuSig2 是 n-of-n 多签方案,签名要求密钥聚合涉及的全体签名者参与,不是 t-of-n 门限签名。想做“多数同意即可”的安排,需要脚本路径等其他机制配合,而不是只靠 MuSig2 本身。
七、延伸
- 阅读版:https://bips.dev/327
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki
- 相关:BIP-340 Schnorr 签名、BIP-341 Taproot、BIP-328 MuSig2 聚合密钥派生、BIP-373 MuSig2 PSBT 字段
- 仓库总目录:https://github.com/bitcoin/bips
