EIP-3068 深度解析:为 BN256 引入 HashToCurve 预编译,让 EVM 内的 BLS 签名验证成为可能
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
本文基于当前仓库 EIPS/eip-3068.md(Ethereum Improvement Proposal 3068,状态 Stagnant,类型 Standards Track / Core)编写。该提案为以太坊 EVM 中的 BN256(alt_bn128)椭圆曲线新增
HashToG1/HashToG2哈希到曲线预编译,其直接应用场景是:在链上以可负担的 Gas 成本验证任意消息的 BLS 签名、聚合签名与 DKG 组签名。读完本文,你将掌握该提案的完整算法流程(从HashToBase域元素生成到 Fouque–Tibouchi 确定性映射、再到 G2 的 twist 映射与余因子消去),理解其 Gas 估算方法、设计自由度以及 BN256 曲线自身的安全降级背景,并能在仓库中找到全部佐证材料。
一、背景与动机:EVM 中缺失的那块 BLS 拼图
1.1 已有的 BN256 密码学原语
以太坊在拜占庭硬分叉后通过 EIP-196 与 EIP-197 引入了基于alt_bn128(即 BN256)曲线的三个预编译合约:
| 预编译 | 地址 | 作用 |
|---|---|---|
ECADD | 0x06 | 椭圆曲线点加法 |
ECMUL | 0x07 | 椭圆曲线标量乘法 |
| Pairing check | 0x08 | 最优 ate 配对检查 |
曲线定义(见 EIPS/eip-196.md):
Y^2 = X^3 + 3 over the field F_p with p = 21888242871839275222246405745257275088696311157297823662689037894645226208583随后 EIP-1108 依据 Go/Parity 客户端底层库(如 Cloudflare bn256 库)的性能优化,大幅降低了这三者的 Gas 成本:ECADD由 500 降至150,ECMUL由 40,000 降至6,000,配对检查由80,000 * k + 100,000降至34,000 * k + 45,000(k为配对个数)。这套原语显著降低了 SNARK 验证与配对运算的上链成本。
1.2 缺口:任意消息的 BLS 签名无法在链上廉价验证
然而,EIP-3068 指出一个明显缺失:EVM 中没有针对 BN256 的哈希到曲线(hash-to-curve)预编译。这直接导致:
- 无法对"任意消息"执行 BLS 签名验证——BLS 签名验证需要把消息哈希映射到 G1 上的点,再执行配对检查;
- 若用 Solidity 实现确定性的哈希到曲线算法,其Gas 成本大约等于一次配对检查的代价,尽管后者所需的实际计算量高出一个数量级——也就是说,链上 Solidity 实现的 hash-to-curve 在计价上被严重高估;
- DKG 协议(如 ETHDKG)可以离线聚合部分签名为组签名,但链上缺少廉价的验证路径。
EIP-3068 的解决方案是:实现一个针对BN256 G1 群的哈希到曲线算法(同时附带 G2 群的版本),使得签名验证的成本收敛到配对检查预编译本身的成本。
1.3 从非确定性 MapToGroup 到确定性映射
原版 BLS 论文(仓库附件 weilsigs.pdf)中的MapToGroup方法在实践中可用,但其非确定性特性让 Gas 成本难以界定——EVM 中需要可预期的计算上限。
EIP-3068 因而采用了 Fouque 与 Tibouchi 在 latincrypt12.pdf(LatinCrypt 2012)中给出的确定性映射方法,该论文证明了其映射与随机预言机(random oracle)不可区分(indifferentiable from a random oracle),这正是签名方案安全性证明所需的关键性质。
二、规范总览:HashToG1与HashToG2
EIP-3068 规范了两个入口函数。先是HashToG1的伪代码(原文照录):
function HashToG1(msg) fieldElement0 = HashToBase(msg, 0x00, 0x01) fieldElement1 = HashToBase(msg, 0x02, 0x03) curveElement0 = BaseToG1(fieldElement0) curveElement1 = BaseToG1(fieldElement1) g1Element = ECAdd(curveElement0, curveElement1) return g1Element end function整体流程可以拆解为三层:
HashToBase:把消息字节串映射为有限域GF(fieldPrime)中的元素(即"哈希到标量");BaseToG1:把域元素确定性映射为 G1 曲线上的点(Fouque–Tibouchi 方法);ECAdd:对两次独立映射得到的点求和,以消除单个映射可能引入的结构偏差。
三、HashToBase:从消息字节到有限域元素
HashToBase的伪代码:
function HashToBase(msg, dsp1, dsp2) hashResult0 = uint256(Keccak256(dsp1||msg)) hashResult1 = uint256(Keccak256(dsp2||msg)) constant = 2^256 mod fieldPrime fieldElement0 = hashResult0*constant mod fieldPrime fieldElement1 = hashResult1 mod fieldPrime fieldElement = fieldElement0 + fieldElement1 mod fieldPrime return fieldElement end function要点解读:
- 入参:
msg为待哈希的字节切片;dsp1、dsp2为域分离参数(domain separation parameters),用于区分不同用途的哈希调用; - 两次 Keccak256:分别计算
Keccak256(dsp1||msg)与Keccak256(dsp2||msg),其结果被解释为uint256; - 模约减技巧:
hashResult0先乘以constant = 2^256 mod fieldPrime再取模,等价于把 512 比特的联合输出(hashResult0, hashResult1)按 256 比特分块归约到模fieldPrime的整数,从而尽量降低模约减带来的偏差; - 最终返回
GF(fieldPrime)上的一个元素。
调用时使用的域分离参数分别为:HashToG1内部两次调用HashToBase(msg, 0x00, 0x01)与HashToBase(msg, 0x02, 0x03);HashToG2内部则使用0x04,0x05、0x06,0x07、0x08,0x09、0x0a,0x0b四组参数(详见后文)。
四、BaseToG1:Fouque–Tibouchi 确定性映射
BaseToG1的伪代码(原文照录),其中所有运算均在有限域GF(fieldPrime)内完成:
function BaseToG1(t) # All operations are done in the finite field GF(fieldPrime) # Here, the elliptic curve satisfies the equation # y^2 == g(x) == x^3 + curveB constant1 = (-1 + sqrt(-3))/2 constant2 = -3 constant3 = 1/3 constant4 = g(1) s = (constant4 + t^2)^3 alpha = inverse(t^2*(constant4 + t^2)) x1 = constant1 - constant2*t^4*alpha x2 = -1 - x1 x3 = 1 - constant3*s*alpha a1 = x1^3 + curveB a2 = x2^3 + curveB residue1 = is_square(a1) residue2 = is_square(a2) index = (residue1 - 1)*(residue2 - 3)/4 + 1 coef1 = ConstantTimeEquality(1, index) coef2 = ConstantTimeEquality(2, index) coef3 = ConstantTimeEquality(3, index) x = coef1*x1 + coef2*x2 + coef3*x3 y = sign0(t)*sqrt(x^3 + curveB) return (x, y) end function function sign0(t) if t <= (fieldPrime-1)/2 return 1 else return fieldPrime-1 end if end function function ConstantTimeEquality(a, b) # This function operates in constant time if a == b return 1 else return 0 end if end function4.1 算法思路:三候选点 + 二次剩余判定
BaseToG1的核心逻辑是:对输入域元素t,构造三个候选 x 坐标x1、x2、x3,计算各自对应的a_i = x_i^3 + curveB,再通过is_square(Legendre 符号)判定:
is_square(a)返回1(a是平方)、-1(a非平方)、0(a为零);index = (residue1 - 1)*(residue2 - 3)/4 + 1将两个二次剩余结果编码为 1、2、3 中的一个,唯一确定哪个候选 x 落在曲线上;- 通过
ConstantTimeEquality生成系数coef1/coef2/coef3,以常数时间方式选出正确的 x(避免条件分支引入时间侧信道); - 最后用
sign0(t)确定 y 的符号,保证映射的确定性。
4.2 辅助函数说明
| 函数 | 语义 | 约定 |
|---|---|---|
inverse(a) | 有限域乘法逆元 | inverse(0) == 0 |
is_square(a) | Legendre 符号 | 平方为 1,非平方为 -1,零为 0 |
sqrt(a) | 有限域平方根 | 假定根存在 |
sign0(t) | 有限域元素符号 | t <= (fieldPrime-1)/2时为 1,否则为fieldPrime-1 |
ConstantTimeEquality(a, b) | 常数时间相等判断 | 相等返回 1,否则 0 |
五、HashToG2与BaseToTwist:经由 twist 曲线映射并消去余因子
G2 群不能直接在基域上描述,EIP-3068 采用"先映射到 twist 曲线,再消去余因子(clear cofactor)"的两步策略。伪代码(原文照录):
function HashToG2(msg) fieldElement00 = HashToBase(msg, 0x04, 0x05) fieldElement01 = HashToBase(msg, 0x06, 0x07) fieldElement10 = HashToBase(msg, 0x08, 0x09) fieldElement11 = HashToBase(msg, 0x0a, 0x0b) fieldElement0 = (fieldElement00, fieldElement01) fieldElement1 = (fieldElement10, fieldElement11) twistElement0 = BaseToTwist(fieldElement0) twistElement1 = BaseToTwist(fieldElement1) twistElement = ECAdd(twistElement0, twistElement1) g2Element = ClearCofactor(twistElement) return g2Element end function function ClearCofactor(twistElement) return ECMul(twistElement, cofactor) end functionBaseToTwist与BaseToG1结构完全同构,只是所有运算发生在扩域GF(fieldPrime^2),曲线方程为y^2 == g'(x) == x^3 + curveBPrime(curveBPrime为 twist 曲线的常数项):
function BaseToTwist(t) # All operations are done in the finite field GF(fieldPrime^2) # Here, the twist curve satisfies the equation # y^2 == g'(x) == x^3 + curveBPrime constant1 = (-1 + sqrt(-3))/2 constant2 = -3 constant3 = 1/3 constant4 = g'(1) s = (constant4 + t^2)^3 alpha = inverse(t^2*(constant4 + t^2)) x1 = constant1 - constant2*t^4*alpha x2 = -1 - x1 x3 = 1 - constant3*s*alpha a1 = x1^3 + curveBPrime a2 = x2^3 + curveBPrime residue1 = is_square(a1) residue2 = is_square(a2) index = (residue1 - 1)*(residue2 - 3)/4 + 1 coef1 = ConstantTimeEquality(1, index) coef2 = ConstantTimeEquality(2, index) coef3 = ConstantTimeEquality(3, index) x = coef1*x1 + coef2*x2 + coef3*x3 y = sign0(t)*sqrt(x^3 + curveBPrime) return (x, y) end function要点:
HashToG2需要4 次HashToBase,因为 G2 的元素由两个GF(fieldPrime^2)元素(各含两个基域分量)构成;BaseToTwist将两个扩域元素分别映射到 twist 曲线上的点,再ECAdd求和;- 关键收尾步骤
ClearCofactor用ECMul(twistElement, cofactor)乘以余因子,把 twist 曲线上的点映射到阶为r的 G2 子群,保证最终点确实落在配对定义域内; inverse、is_square、sqrt在GF(fieldPrime^2)上的实现方法,EIP 指向了 2012-685_Square_Root_Even_Ext.pdf(偶数次扩域上的平方根计算)。
六、Rationale:设计选择与可替换自由度
EIP-3068 在 Rationale 部分明确了以下设计边界(见 EIPS/eip-3068.md):
- 算法来源:
BaseToG1基于 Fouque–Tibouchi 论文 latincrypt12.pdf,并参考 Wahby–Boneh 的 2019-403_BLS12_H2C.pdf 做了修改;HashToG2直接沿用 Wahby–Boneh 论文的路线; HashToBase可替换:规范明确说明HashToBase的选择是自由的,可以轻松更换;- 哈希原语可替换:
HashToBase内部的哈希算法(本提案选用 Keccak256)同样可以修改; - 符号函数的选择:
BaseToG1/BaseToTwist末尾使用sign0确定 y 的符号。EIP 指出,若改用is_square判定,将得到与 Fouque–Tibouchi 论文完全一致的确定性映射,从而能直接套用其"与随机预言机不可区分"的证明;改用sign0是否仍保持不可区分性尚未被证明,这是一个值得注意的开放性安全问题(虽然可能成立)。
七、性能与 Gas 成本估算
EIP-3068 在单台本地机器上实测了各操作的耗时,并据此推算了 Gas 公式(见 EIPS/eip-3068.md):
| 操作 | 输入长度 | 实测耗时 | 备注 |
|---|---|---|---|
ECMUL | — | 68 µs | 基线,当前 Gas 为 6,000(EIP-1108) |
HashToG1 | 32 字节 | 94 µs | — |
HashToG1 | 1024 字节 | 105 µs | — |
HashToG2 | 32 字节 | 886 µs | — |
HashToG2 | 1024 字节 | 912 µs | — |
由此得到的建议 Gas 公式:
HashToG1:8500 + len(bytes)HashToG2:80000 + 3 * len(bytes)
其中len(bytes)为输入消息的字节长度,体现了哈希输入越长、成本线性上升的定价逻辑。以 32 字节消息为例,HashToG1约 8,532 gas,HashToG2约 80,096 gas——前者与一次配对检查(34,000 * 1 + 45,000 = 79,000gas,EIP-1108 定价)处于同一量级甚至更低,这正是"把签名验证成本收敛到配对检查成本"这一目标的直接体现。
八、安全性考量:BN256 的安全降级背景
EIP-3068 的 Security Considerations 部分披露了一个与曲线本身相关的安全背景(见 EIPS/eip-3068.md):
- 由于 2015-1027_exTNFS.pdf 所代表的扩展塔数域筛法(exTNFS)进展,BN256 原本宣称的 128 位安全强度已不再成立;这一点 Cloudflare 的 bn256 库也提及过;
- 关于安全强度具体下降多少存在不同估计,EIP 附上了 2016-1102_Assessing_NFS_Advances.pdf 与 2017-334.pdf 两篇论文;较保守的估计认为 BN256 仅剩约 100 位安全强度;
- 这一降级影响被 madnet.pdf(MadNet 白皮书)记录,MadNet 的缓解措施是:要求部分组签名附带 Secp256k1 签名才视为有效(EIP 作者自述参与 MadNet 开发并协助撰写该白皮书);
- 关键边界:上述安全顾虑源于 BN256 曲线配对本身,与"是否引入本提案的 hash-to-curve 预编译"无关——任何使用
0x08配对预编译的合约都受其影响。
九、兼容性、测试与实现现状
- 向后兼容:EIP-3068 明确声明"没有向后兼容性问题"(
There are no backward compatibility concerns)。新增预编译不改变既有预编译的语义;按照惯例,新预编译应占用 256 以下的保留地址区间(EIP-196 引入0x06/0x07、EIP-197 引入0x08均遵循此惯例,见 EIPS/eip-196.md); - 测试用例与实现:原文档中
Test Cases与Implementation两节均标注为TBD(待定),即该提案发布时尚未提供标准测试向量与参考实现; - 提案状态:该 EIP 当前状态为Stagnant(停滞),创建于 2020-10-23,作者 Dr. Christopher Gorman,
requires字段声明依赖 EIP-198 与 EIP-1108。读者若在以太坊主网上并未看到 0x09 等新地址的 hash-to-curve 预编译上线,与这一状态一致。
十、结论与仓库索引
EIP-3068 提供了一套完整、确定性的 BN256 哈希到曲线方案:以 Keccak256 + 域分离参数生成有限域元素(HashToBase),经 Fouque–Tibouchi 确定性映射进入 G1(BaseToG1),对 G2 则先映射到 twist 曲线(BaseToTwist)再通过ClearCofactor消去余因子。它补齐了 EVM 中"配对检查可用、但任意消息无法廉价哈希到曲线"的缺口,使链上 BLS 签名验证、聚合签名与 DKG 组签名验证在成本上趋近于一次配对检查。同时,提案也诚实地披露了 BN256 因 exTNFS 进展而降至约 100 位安全强度的背景,以及sign0替换is_square后不可区分性证明缺失的开放问题——这些正是任何基于 BN256 构建密码学应用的团队在采用前必须评估的风险。
仓库内延伸阅读
- 提案正文:EIPS/eip-3068.md
- 曲线与加法/标量乘法预编译定义:EIPS/eip-196.md
- 配对检查预编译定义:EIPS/eip-197.md
- 预编译 Gas 下调:EIPS/eip-1108.md
- 本提案依赖的模幂预编译:EIPS/eip-198.md
- 算法论文附件:assets/eip-3068/(Fouque–Tibouchi 确定性映射 latincrypt12.pdf、Wahby–Boneh 哈希到曲线 2019-403_BLS12_H2C.pdf、原版 BLS 论文 weilsigs.pdf、扩域平方根 2012-685_Square_Root_Even_Ext.pdf、安全评估论文三篇与 MadNet 白皮书)
版权说明:EIP-3068 原文以 CC0 放弃版权(见仓库根目录 LICENSE.md),本文基于该公开规范编写,未引入任何外部网站资料。
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考