1. 引言
在What’s the deal with hash functions in Zero Knowledge?中,研究了哈希函数对ZKP场景的用途。当前有各种ZK-friendly 哈希函数设计,各有优缺点,且针对不同的性能维度进行了优化,如:
- MiMC
- GMiMC
- Poseidon
- Poseidon2
- Rescue
- Griffin
- Anemoi
- Neptune
- Grendel
- Reinforced Concrete
- Tip5
- Monolith
- 等等
如何从中选择适合特定应用场景的哈希函数?
选择依据取决于多个维度,如:
- 所用的ZKP证明系统
- 应用场景的主要开销指标
本文提供了2种决策树方案供选择。
2. 仅关心fast prover的应用场景——Griffin
仅考虑prover性能的情况下,即,使ZK电路内部开销最小化的情况下,来选择最好的哈希函数。
自从第一次尝试用MiMC最小化乘法次数以来,研究人员已经取得了长足的进步。在What’s the deal with hash functions in Zero Knowledge?中,解释了low-degree equivalence的设计原则。这些设计特别适于让prover开销最小化,其主要与众不同的特性在于:
- 同时使用了 y = x d y=x^d y=xd和 y = x 1 / d y=x^{1/d} y=x1/d。
- 从而实现了具有小轮数的安全哈希函数。其中小轮数,对应为更少数量的约束。
- 在ZK电路中,昂贵的 y = x 1 / d y=x^{1/d} y=x1/d计算,实际与 y = x d y=x^d y=xd一样便宜,因为有等价表示: y = x 1 / d ≡ x = y d y=x^{1/d}\equiv x=y^d y=x1/d≡x=yd。
第一个成功使用该设计方法的哈希函数为Rescue,后经小幅优化为Rescue-Prime。不过研究人员又进一步优化,引入了Griffin和Anemoi哈希函数。
Griffin和Anemoi哈希函数的作者,使用不同配置和证明系统,比较了其哈希函数性能:
- 当用于R1CS-based ZKP系统中时,其具有大幅优势——如Poseidon哈希需要240个约束,而Griffin仅需要96个约束。
- 当用于AIR-based STARKs和Plonk证明系统中(使用原始Plonk-gate)时,也具有大幅优势——如Poseidon需要518个gate,而Griffin仅需要173个gate。
Griffin和Anemoi哈希函数在不同ZKP系统中提供了类似的性能,如何从中选择呢?
- 某些配置下Griffin要更好一点,某些配置下Anemoi略占优势。
- Griffin需要更少的
y
=
x
1
/
d
y=x^{1/d}
y=x1/d计算,使得其在现代CPU上evaluate更快。具体见https://github.com/anemoi-hash/hash_f64_benchmarks(Rust)benchmark。
其哈希性能更快,对ZK电路外的Merkle tree预计算 很重要。与此同时,对于必须填充traces的阶段,可贡献更快的ZK proving。因此,选择Griffin。
3. ZKP证明系统之外的哈希同等重要
尽管ZK电路内的Griffin/Anemoi/Rescue很快,但与原生暗哈希相比,其仍相对较慢。
CPU中,计算 y = x 1 / d y=x^{1/d} y=x1/d,要比计算 y = x d y=x^d y=xd low-degree计算,慢得多。对于某些 原生性能与ZK prover性能同等重要 的应用场景,应避免选择Griffin或Anemo。如:
- recursive STARK中:需要在每个递归步骤中,原生计算huge Merkle tree,同时,要ZK证明该计算的正确性。
- Fractal,所使用哈希函数的原生性能慢,使得prover花费大多数时间用于构建Merkle tree。
此时,怎样是最好的哈希函数呢?——首要回答的问题是:
- 所使用ZKP系统是否支持lookup argument?——
- 支持,且大素数域:Reinforced Concrete
- 支持,且小素数域:Monolith
- 不支持:Poseidon2
- 所使用的ZKP系统的原生素数域是什么?
不过,当使用Reinforced Concrete时,还需考虑:
- Reinforced Concrete使用lookup tables来提升原生哈希性能,但可能易受cache-based side-channel攻击。尽管当前文献或其它公开场合并未发生类似攻击,但未来可能有,这个应牢记于心。若对所应用场景有影响,则应转而选择Poseidon2。
3.1 ZKP系统支持lookup argument
对于某些 原生性能与ZK prover性能同等重要 的应用场景,若所使用的ZKP系统支持lookup argument,则可使用如下采用lookup原生性能设计的哈希函数,如:
- Reinforced Concrete
- Tip5
- Monolith
根据支持lookup argument 的ZKP系统 所采用的原生素数域,来选择不同的哈希函数:
- 1)若为big ≈ 256 \approx 256 ≈256 bit素数域,如BLS12-381或BN254,则可使用Reinforced Concrete。Reinforced Concrete:为首个在大素数域使用lookup argument的哈希函数,从而相比于之前的哈希函数,对大域size,具有更快的原生哈希性能。如使用BN254,Poseidon哈希为 20.4 μ s 20.4\mu s 20.4μs,而Reinforced Concrete为 3.5 μ s 3.5\mu s 3.5μs。
- 2)若为small 素数域,如64-bit Goldilocks域(当前已用于FRI-based Plonky2证明系统中),或,31-bit Mersenne素数域(当前已用于Plonky3中),则可使用Monolith哈希函数。Monolith为当前最快原生哈希的ZK-friendly哈希函数。其性能甚至接近了传统哈希函数(如SHA3)的原生哈希速度。
3.2 ZKP系统不支持lookup argument
对于某些 原生性能与ZK prover性能同等重要 的应用场景,若所使用的ZKP系统不支持lookup argument,也有很多其它设计选择:
- 1)Poseidon,很长时间以来都被认为是具有最快原生性能的ZK-friendly哈希函数,其最近有改进版——Poseidon2,在保持相同ZK性能的情况下,不同设置下,其原生性能比Poseidon提升约40%。
4. 不信任所有这些新哈希函数
设计既安全又高效的新哈希函数并不容易。经验表明,尽管设计者尽了最大努力来确保哈希函数的安全,但密码分析师还是想出了新的、更有效的方法来破坏新的对称原语的安全性。因此,理想情况下,新的哈希函数应该经过几年的战斗测试,以便研究人员更好地了解给定设计的安全性。然后,在多年未能破解哈希函数之后,人们终于可以开始信任该设计。从这个意义上说,2019年(4年前)发布的Poseidon或Rescue Prime,或者更老的MiMC,可能是最好的选择。由于它们的年龄,这些也是采用最广泛的哈希函数。因此,与其他ZK友好的哈希函数相比,攻击者更有动机破坏Poseidon、Rescue和MiMC的安全性。此外,它们是一个赏金计划的一部分,目的是进一步了解它们的安全。
最终,获得设计安全性信任的最佳方式是经历多年的标准化之旅。到目前为止,ZK友好的哈希还没有被NIST等机构标准化。此外,在zkproof.org上开发的社区标准中还没有ZK友好的哈希。然而,这种情况可能会改变。随着对零知识、同态加密和多方计算用例的对称密码和哈希函数的需求不断增加,NIST正在考虑启动这些设计的标准化过程(见NIST First Call for Multi-Party Threshold Schemes),并非常有兴趣听取行业的用例报告。
最后,您可以使用NIST标准化的哈希函数,如SHA-256,这是一个非常保守的选择。几乎所有流行的证明系统代码实现都为SHA-256提供了定制电路,虽然它们的效率仍然远低于为ZK用例优化的哈希函数设计,但若想尽可能保守或有外部约束,这可能是一个有效的权衡点。
5. 不要,未证明安全的哈希函数
若压根不信任任何新的密码学哈希函数,可使用基于,常见于数字签名的经典hardness assumption(如discrete logarithm problem),的哈希函数,目前在一些ZK框架(如Halo2)中已实现,如:
- Pedersen哈希函数
- 基于Pedersen的lookup-friendly 接班人:Sinsemilla哈希函数
尽管这些哈希函数,相比于之前的密码学哈希函数,可能:
- 原生哈希更慢,证明性能也更慢
- (对fixed size inputs)仅提供抗碰撞性,no full pre-image resistance
- 不具备抗量子安全性,其安全性会reduce为discrete logarithm hardness assumption.
- 仅可作为使用large ≈ 256 \approx 256 ≈256 bit素数域证明系统的备选项,因在该大素数域中,才可认为discrete-log是hard的。
6. 决策树
有2棵决策树,帮助做哈希函数选择:
- 1)根据用户场景来选择:
- 2)根据信任假设和哈希函数的新颖性来选择:
7. 结论
为ZK应用场景选择合适的哈希函数很难决策,但可从如下维度来判断:
- 1)是否仅关注prover性能?若是,则选择Griffin。
- 2)是否既关注prover性能也关注原生哈希性能?
- 若是,且支持lookup argument,且大素数域:Reinforced Concrete
- 若是,且支持lookup argument,且小素数域:Monolith
- 若是,且不支持lookup argument:Poseidon2
- 3)是否主要关心已经建立的设计,并为安全性提供合理的论证?若是,则选择Poseidon 或 Rescue-Prime,具体取决于性能评价是否关注原生哈希。若关注电路之外的原生哈希性能,则选Poseidon,否则选Rescue-Prime。
参考资料
[1] TACEO博客 2023年10月10日 How to choose your ZK-friendly hash function?