协议演进 / BIP/比特币改进提案 / BIP-374
BIP-374
定义一种 64 字节的零知识离散对数相等证明,让证明者在不泄露私钥的前提下,证明两个公钥点确由同一个标量生成。本 BIP 目前处于草案状态。
一、档案卡
| 编号 | BIP-374 |
|---|---|
| 标题 | Discrete Log Equality Proofs |
| 作者 | Andrew Toth <[email protected]>、Ruben Somsen <[email protected]>、Sebastian Falbesoner <[email protected]> |
| 指定日期 | 2024-12-26 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Draft(草案) |
| 阅读版 | https://bips.dev/374 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki |
二、放在哪一族
密码学原语族:它不属于某个钱包功能,而是给上层协议提供一块可复用的证明积木。
最直接的下游是静默支付(Silent Payments)一线:BIP-352 规定发送方如何用 ECDH 共享秘密算出收款输出脚本,BIP-375 在 PSBT 中发送静默支付时,就用 BIP-374 的证明来担保 ECDH 份额算对了。凡是“一方用私钥算出某个点、另一方需要在不见私钥的情况下核验”的协议,都可能用到它。
它的记号与约定沿用 BIP-327(MuSig2)的 Notation 一节,随机数处理思路则参照 BIP-340 的默认签名做法。
三、它要解决什么
先看证明本身要表达什么。给定椭圆曲线点 A、B、C、G 与一个只有证明者知道的标量 a,其中 A = a·G、C = a·B。证明者要向验证者证明:A 与 C 确实出自同一个 a——但不能透露 a 的任何信息。这就是离散对数相等(DLEQ)证明,一种零知识证明。
典型场景是 ECDH:A 与 B 是双方的 ECDH 公钥,C = a·B 是共享秘密。证明成立,就说明生成 A 的私钥与算出 C 用的是同一把,共享秘密没有算错人、算错键。
为什么静默支付特别需要它?BIP-352 要求发送方用“给输入签名的同一批私钥”算出的 ECDH 共享秘密去生成收款输出脚本。签名算错,交易会被共识拒绝,错误当场暴露;但输出脚本算错,交易仍然是共识有效的——一旦广播出去,资金可能就打到谁也花不了的脚本上,永久损失。
在多方协作(尤其是 PSBT 多签名者)场景里,算脚本的一方与持私钥的一方可能不是同一个人。有了 DLEQ 证明,签名实体可以向其他参与方证明“我交出的 ECDH 份额确由对应私钥算出、输出脚本生成正确”,同时不交出私钥。
四、规则本身
4.1 证明长什么样
一份证明只有 64 字节:前 32 字节是挑战值 e,后 32 字节是响应值 s,仅此而已(proof = bytes(32, e) ‖ bytes(32, s))。
背后的思路是经典的交互式证明非交互化:证明者取随机标量 k,算 R₁ = k·G、R₂ = k·B,以 e = hash(R₁ ‖ R₂) 为挑战,再算 s = k + e·a。只给出 C、e、s,不会泄露 a 或 k。
验证者只需用 e 与 s 反推:R₁ = s·G − e·A,R₂ = s·B − e·C,再检查 e 是否等于对 R₁、R₂ 的哈希。两式代入 s 的定义都能还原出 k·G 与 k·B,因此哈希对得上,就证明 A 与 C 同源于 a。
4.2 生成算法(GenerateProof)
输入:秘密标量 a、曲线点 B、32 字节辅助随机数据 r、生成点 G,以及可选的 32 字节消息 m。
要点如下:
- a 为 0 或不小于曲线阶 n、B 为无穷远点时失败;
- 先算 A = a·G、C = a·B;
- 把 a 的字节与辅助随机数据的带标签哈希(标签
BIP0374/aux)逐字节异或,再连同 A、C 与消息作带标签哈希(标签BIP0374/nonce),取模得到一次性随机数 k,k 为 0 时失败;每份证明都应使用新鲜的辅助随机数据; - 挑战 e 是把 A、B、C、G、R₁、R₂ 与消息一并作带标签哈希(标签
BIP0374/challenge)后取模 n 的结果; - s = (k + e·a) mod n,证明即 e 与 s 的拼接;返回前必须先自验一遍,验证失败则中止。
生成点 G 被设计为显式输入:其他 BIP 都直接用 secp256k1 的生成点,这样传参让同一算法也能用于 secp256k1 上的其他生成点。可选消息 m 让上层协议可以把证明绑定到一个复合陈述上,而不只是“知道某个标量”。
4.3 验证算法(VerifyProof)
输入 A、B、C、64 字节证明、G 与可选消息 m。验证者拆出 e 与 s(任一不小于 n 即失败),按 4.1 的两式重算 R₁、R₂(任一点或 R₁、R₂ 为无穷远点即失败),再重算挑战哈希与 e 比对:一致且全程无失败,才算验证成功,即 A 与 C 确由同一标量 a 生成。
五、谁必须动
普通持币人:无直接动作。证明在钱包与协作方之间生成和核验,用户不手工接触。
钱包开发者:凡实现“代人计算 ECDH 份额、再请他人核验”的流程——首要就是 BIP-375 的静默支付 PSBT 发送——都要按本规范实现 GenerateProof 与 VerifyProof,并为每份证明使用新鲜随机数据;原文附有 Python 参考实现与测试向量生成脚本。
硬件钱包与签名者:作为签名实体时,可能需要对外出具 DLEQ 证明以自证份额正确;作为核验方时,要在接受他人算出的输出脚本之前先验明证明。
全节点与矿工:无需动作。证明只在链下传递,不进区块、不改共识,向后兼容所有旧客户端。
六、现在算不算数,以及一个常见误读
状态为 Draft(草案),版本 0.3.0。原文变更记录显示它仍在迭代:0.2.0 把可选消息纳入随机数计算,0.3.0 把挑战 e 明确按标量处理(对曲线阶取模,并拒绝 e 不小于 n 的证明)。原文的参考实现与测试向量一节在仓库中仍标 TODO,但另行给出了 bip-0374 目录下的 Python 参考代码与向量生成方式。把它当作“接口已基本成形、细节仍可能调整”来读更稳妥。
常见误读:“有了 DLEQ 证明,输出脚本就绝对不会错、资金绝对安全。”不对。证明担保的范围很具体:某个 ECDH 份额 C 确由生成 A 的同一私钥算出。它不担保金额、找零、地址录入等其他环节不出错;验证方若跳过验明就直接采用他人算出的脚本,证明等于没用。
七、延伸
- 阅读版:https://bips.dev/374
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki
- 相关:BIP-352 静默支付、BIP-375 用 PSBT 发送静默支付、BIP-327 MuSig2(记号约定)、BIP-340 Schnorr 签名
- 仓库总目录:https://github.com/bitcoin/bips
