ZKP中的哈希函数

1. 引言

后续博客:

当暴露在ZK空间中时,对于普通crypto工程师来说,通常只需很少的时间就可以偶然发现一些外来的哈希函数——很可能是Poseidon。本文,将介绍ZK中高效哈希函数的历史,并解释为何不简单地使用现有已标准化哈希函数SHA-2/3。

也可参考:

2. 为何需要Poseidon之类的哈希函数?

当前,许多ZK框架都基于Poseidon哈希函数实现,原因何在?

  • membership proofs和Merkle tree commitments 对许多ZK应用场景至关重要。这两种情况下:
    • 都需要使用Merkle tree来积累很多数据元素。
    • 并使用ZKP系统来证明叶子节点到root的path。
    • Merkle tree中每个节点的计算,正是基于某密码学哈希函数的哈希运算。

假设有Merkle tree中某叶子节点,并向使用SNARK或STARK证明其ownership。最终的ZK电路中包含多个哈希计算,直到到达该Merkle tree的root。随着Merkle tree的高度增加,生成proof的性能将高度依赖于所使用哈希函数的效率。这也是为何在ZK场景,没人用传统已标准化哈希函数(如SHA-256、SHA-3、Blake等)的原因。尽管这些传统已标准化哈希函数在现代CPU上运行非常快。

当前现状为:

  • 大多数现代ZKP系统都基于更大素数域运算——如Halo2的256-bit、Plonky2的64-bit、Plonky3的31-bit,其性能开销通常与电路中的乘法运算相关。
    • 对R1CS约束,通常仅关注乘法次数
    • Plonkish系统porver开销随trace width、trace depth、transition多项式degree而增加,即也取决于电路的乘法复杂度。

传统哈希函数,通常基于位运算,而不是基于素数域元素运算的。这有两个重要的含义:

  • 1)内部状态的哈希计算必须至少是256位的,在Plonkish表示中,这意味着large trace width,或large trace depth。
  • 2)需要在ZKP的原生素数域中模拟二进制运算,将:
    • 要求证明每个输入元素为a bit(即对每个bit证明 x ( x − 1 ) = 0 x(x-1)=0 x(x1)=0)。
    • 模拟AND/XOR,需要做乘法运算: x 1   a n d   x 2 = x 3 ⇒ x 1 ⋅ x 2 = x 3 x_1\ \mathsf{and}\ x_2=x_3 \Rightarrow x_1 \cdot x_2=x_3 x1 and x2=x3x1x2=x3 x 1   x o r   x 2 = x 3 ⇒ x 1 + x 2 – 2 ⋅ x 1 ⋅ x 2 = x 3 x_1\ \mathsf{xor}\ x_2=x_3 \Rightarrow x_1 + x_2 – 2\cdot x_1 \cdot x_2 = x_3 x1 xor x2=x3x1+x2–2x1x2=x3。这将导致大量的乘法运算,从而导致large trace,最终导致prover性能非常低效。

因此,研究人员开发了新的哈希函数,这些新的经过优化的哈希函数,可在ZK证明系统中高效运行。这些哈希函数定义为直接基于素数域运算,从而抵消了上述缺点。此外,引入了额外的技术来最小化ZK电路中的乘法次数。因此现代ZK友好哈希函数可 以由少于100次的乘法来构建(如2022年论文 Horst Meets Fluid-SPN: Griffin for Zero-Knowledge Applications)。与仅证明传统哈希函数输入为bits(忽略实际哈希计算)相比,这已经大大减少了乘法运算次数。

在这里插入图片描述

广义来说,新的哈希函数可分为三大类:

  • 1)Low-degree round functions 哈希函数:如MiMC、GMiMC、Poseidon、Poseidon2、Neptune。
  • 2)“Low-degree equivalent” round functions 哈希函数:如Rescue、Rescue-Prime、Anemoi、Griffin、Grendel。
  • 3)Lookup-based round functions 哈希函数:如Reinforced Concrete、Tip5、Monolith。

现有已标准化哈希函数SHA-2/3、Blake等,具有非常快的plain(电路外)哈希性能,但受限于其算术性质,在ZK电路内具有很高的开销。

  • MiMC为首个实用 Low-degree round functions 的哈希函数,基于MiMC方向,后来有了Poseidon——相比于传统哈希函数,实现了在ZK电路内的性能飞跃。
  • 后来,研究人员基于“Low-degree equivalent” round functions,进一步改进了电路内性能,从而有了Rescue、Rescue-Prime和Griffin。
    • ZK电路内,Griffin比Poseidon更便宜,但Griffin在电路外的哈希开销更昂贵。
  • 百万美元的问题是:能否得到与SHA-3或类似的速度,但仍能提高ZK电路内部开销的新哈希函数?
    事实上,这个问题是有答案的!答案是肯定的——当ZKP证明系统支持lookup argument时。
    • Lookup-based round functions 哈希函数【愿SHA-3速度与你同在】

3. Low-degree round functions 哈希函数

Low-degree round functions 哈希函数,可看成是初代ZK友好哈希函数,起源于MiMC。
很多哈希函数,都基于MiMC和GMiMC构建,如:

  • Poseidon
  • Poseidon2
  • Neptune

除依赖于 Low-degree round functions 之外,大多数通常都基于power map y = x d y=x^d y=xd 构建,其中 d d d 值取决于具体素数域, d d d值通常为 3 , 5 或 7 3,5或7 3,57

Low-degree round functions 哈希函数:

  • 每轮就有相对小数量的乘法运算次数
  • 需要很多轮,以确保安全

总体来说,比基于bits运算的标准化哈希函数(如SHA-2)性能要好得多,且在做密码学分析攻击时,分析起来也相对直接。

4. “Low-degree equivalent” round functions 哈希函数

“Low-degree equivalent” round functions 哈希函数,基于如下发现:

  • 在ZK电路中,不必直接对给定电路的约束系统进行建模。对不同的约束系统进行建模就足够了,当且仅当原始约束系统得到满足时,该约束系统才得到满足。

如:

  • 假设电路计算 y = x 1 / d y=x^{1/d} y=x1/d,可直接构建某约束来直接证明 y = x 1 / d y=x^{1/d} y=x1/d
  • 另一种方法是证明 y = x 1 / d y=x^{1/d} y=x1/d的等价表示—— y d = x y^d=x yd=x
  • d d d小,而素数域大时,则 1 / d 1/d 1/d是一个相当大的指数,需要进行多次乘法运算。但是, y d = x y^d=x yd=x为其equivalent constraint of low degree,适于在ZK电路中高效表示。

使用 y = x 1 / d y=x^{1/d} y=x1/d power map的设计:

  • 相同的安全性,需要的轮数更少
  • 相比于仅依赖Low-degree round functions 的哈希函数,通常在证明系统中具有更高效的表示。——这是重大利好,因为ZK友好哈希函数的设计目的之一,就是改进ZK电路内的性能。

但是“Low-degree equivalent” round functions 哈希函数 的这种改进是有代价的,当用于在电路外(将“电路外”,称为,plain)计算哈希时,必须直接计算 y = x 1 / d y=x^{1/d} y=x1/d,这比计算 y = x d y=x^{d} y=xd要慢得多。因此,基于“Low-degree equivalent” round functions 设计的哈希函数,其相对于,Low-degree round functions 哈希函数(如Poseidon),通常plain哈希性能要更慢。

遵循 “Low-degree equivalent” round functions 策略的哈希函数有:

  • Rescue
  • Rescue-Prime
  • Anemoi
  • Griffin
  • Grendel:采用Legendre symbol,具有更低效的构建。

5. Lookup-based round functions 哈希函数

Lookup-based round functions 哈希函数,为第三代且最新的一类哈希函数,其遵循现代ZKP系统发展趋势,使用lookup tables来让计算更便宜。主要在于如下发现:

  • 当基于大素数域运算时,可将域元素分解为更小的元素(如8-bit size),然后做table lookup,将结果组合回某域元素。

这种方法有多个优势:

  • 1)table lookup在电路外是快速的,(当ZKP证明系统支持lookup argument时)在ZK电路内也相对便宜。
  • 2)对应的安全性高——特别是应对algebraic attacks。因此仅需要少量轮数就行。
    • 缺点在于,底层的证明系统必须支持lookup arguments,从而支持Lookup-based round functions 类型的哈希函数。

遵循Lookup-based round functions的:

  • 首个哈希函数为:Reinforced Concrete:针对约256-bit大素数域做了高度优化。在电路外的性能相比其它ZK友好哈希函数要快得多,但相比于SHA-3来说仍然要慢得多。
  • Tip5:基于Reinforced Concrete思想,但针对的是Plonky2中所使用的特殊64-bit素数域,而构建的哈希函数。
  • Monolith:针对更通用的域(如同时适用于Plonky2的64-bit域,和Plonky3的31-bit域),为首个实现与SHA-3电路外性能相当的ZK友好哈希函数。

参考资料

[1] TACEO 2023年8月17日博客 What’s the deal with hash functions in Zero Knowledge?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言都有相应的实现方式,可以应用于各种不同的场景。C语言的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言用于封装代码的单元,可以实现代码的复用和模块化。C语言定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言用于存储同类型数据的结构,可以通过索引访问和修改数组的元素。字符串是C语言用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值