Jim Miller关于 Fiat-Shamir transformation和ZKP的开篇blog。文章相对基础,可以帮助初学者快速理解交互式零知识证明和Fiat-Shamir变换的问题:https://blog.trailofbits.com/2021/02/19/serving-up-zero-knowledge-proofs/#comments
这个漏洞对所有未规范使用Fiat-Shamir变换的证明系统都产生威胁。
ZKP & Fiat-Shamir变换
ZKP简介
零知识证明允许您(证明者)向另一方(验证者)证明您知道一些秘密的价值,而不必暴露价值本身。
安全性:soundness,它有一个正式的、定义良好的技术定义。如果恶意的证明者不能创建看似有效的虚假证明,那么ZK证明就是合理的。换句话说,验证者不会被一个不好的证明所欺骗。
类比“网球”
用一个网球类比来形象化ZKP和Fiat-Shamir变换。验证者和验证者是站在网的相对两侧的网球选手。证明者试图向验证者证明他们擅长网球。
(1)P将球击向V
(2)V将随机速度、位置、旋转量等发送回P
(3)P必须将球击回球场上的目标点。
如果P击中目标,验证者将他们归类为优秀的网球运动员(good:证明有效)。如果他们没有击中目标,他们就被归类为糟糕的网球运动员(bad:证明无效)。
假设P意识到V每次都把网球送到相同的位置。也许P不擅长打网球,但可以只练习从那个准确的位置击球。尽管P不能从任何位置击中目标,但可以从准确的位置击中目标,并欺骗V。因此,糟糕的随机性会破坏该方案的稳健性(soundness),也会破坏真正的ZK方案。
ZKP与Fiat-Shamir变换
这种网球式的类比是密码学各个领域中常见的挑战/响应协议。在ZK空间中,这些sigma协议有三个步骤:
- P首先发送给V一个初始消息,即承诺消息(Commitment)。
- V回复P一条真正随机的消息,即挑战消息(Challenge)。
- P返回一条响应(Response)消息给V,该消息直接依赖于Commitment消息和Challenge消息,然后V验证该消息为有效或无效。
许多ZK方案都采用sigma协议的形式,这是一种交互式协议,Fiat-Shamir变换可以将sigma协议转换为非交互式协议:使用hash函数代替V的随机响应,P将消息输入到hash函数中,并使用输出作为其挑战消息。
Fiat-Shamir变换的安全性
- 假设哈希函数返回完全随机的输出,即将哈希函数建模为random Oracle(这是一个有争议的话题,但它已经在各种应用程序中使用)
- 关于hash函数的输入:以网球为例,假设使用一堵墙(hash)来返回网球,但由于某种原因,墙内部的随机生成只与速度和旋转有关,而与位置无关。这意味着只要速度和旋转是相同的,P将从不同的位置得到相同的挑战(即,球将被返回到球场上的相同位置)。这些挑战不再是真正随机的,导致P能打破soundness。
对哈希函数的输入的微小差异可能会对协议的安全性产生非常微妙但严重的影响
Schnorr protocol为例
P向V证明他知道secret key
X
{\rm X}
X,对应的public key
Y
=
g
X
{\rm Y= g^X}
Y=gX,证明协议:
用Fiat-Shamir变换转换成非交互协议:
漏洞
如果将生成challenge简单定义为 C = H a s h ( B ) {\rm C = Hash(B)} C=Hash(B),敌手可以生成一个伪造的有效证明:
- P K ′ {\rm PK'} PK′是一个不知道对应私钥的公钥
- 设 B = P K ′ , C = H a s h ( B ) {\rm B=PK',C=Hash(B)} B=PK′,C=Hash(B).
- 随机选取 Z {\rm Z} Z.
- 令
P
K
=
(
g
Z
/
P
K
′
)
1
/
C
{\rm PK=(g^Z/PK')^{1/C}}
PK=(gZ/PK′)1/C.
它允许P为与另一方的公钥 P K ′ {\rm PK'} PK′相关的私钥创建虚假证明。
改进
通过调整计算 C C C的方式可以避免这个问题:设置 C = H a s h ( B , P K ) {\rm C = Hash(B, PK)} C=Hash(B,PK)或 C = H a s h ( B , P K , g ) {\rm C = Hash(B, PK, g)} C=Hash(B,PK,g)。要确保P的每一部分输入都放在哈希函数中!