零知识证明(Zero-Knowledge Proof,简称ZKP)系统,使得持有相关证据 ω \omega ω的证明者 P \mathcal{P} P在不泄露 ω \omega ω的前提下,能够向验证者 V \mathcal{V} V证明与 ω \omega ω相关的语句 ι \iota ι是成立的。举例, P \mathcal{P} P知道离散对数难题 ( G , g , y ) (\mathbb{G}, g, y) (G,g,y)的解 x x x(i.e. g x = y g^x = y gx=y),这里的证据 ω : = x \omega := x ω:=x,语句 ι : = “ P 知 道 y 的 离 散 对 数 解 ” \iota := “\mathcal{P}知道y的离散对数解” ι:=“P知道y的离散对数解”。
接下来给出ZKP的正式化定义。假设 L = def { ι : ∃ ω s.t. C h e c k ( s t r , ι , ω ) = 1 } L \overset{\text{def}}{=} \{ \iota : \exists \omega ~ \text{s.t.} ~ \mathsf{Check}(str, \iota, \omega) = 1 \} L=def{ι:∃ω s.t. Check(str,ι,ω)=1}, Z K P = ( S e t u p , P r o v e , V r f y , C h e c k , S i m , E x t ) \mathsf{ZKP} = (\mathsf{Setup}, \mathsf{Prove}, \mathsf{Vrfy}, \mathsf{Check}, \mathsf{Sim}, \mathsf{Ext}) ZKP=(Setup,Prove,Vrfy,Check,Sim,Ext)是一组六元概率多项式时间算法,
ZKP满足如下4个性质:完备性(Completeness)、可靠性(Soundness)、自适应零知识性(Adaptive Zero-Knowledge)和自适应知识论证性(Adaptive Argument of Knowledge)。
完备性,若协议双方诚实运行算法,系统出错的概率为可忽略函数,
P r [ s t r ← S e t u p ( 1 λ ) ∧ C h e c k ( s t r , ι , ω ) = 1 ∧ π ← P r o v e ( s t r , ι , ω ) : V r f y ( s t r , ι , π ) = 0 ] ≤ n e g l ( λ ) 。 \mathrm{Pr} [ str \gets \mathsf{Setup}(1^\lambda) \land \mathsf{Check}(str, \iota, \omega) = 1 \\ \land \pi \gets \mathsf{Prove}(str, \iota, \omega) : \mathsf{Vrfy}(str, \iota, \pi) = 0 ] \leq \mathsf{negl}(\lambda)。 Pr[str←Setup(1λ)∧Check(str,ι,ω)=1∧π←Prove(str,ι,ω):Vrfy(str,ι,π)=0]≤negl(λ)。
可靠性,若语句 ι ∗ ∉ L \iota^* \notin L ι∗∈/L不成立,那么 P ∗ \mathcal{P}^* P∗成功忽悠 V \mathcal{V} V的概率为可忽略函数,
P r [ s t r ← S e t u p ( 1 λ ) ∧ A P ∗ ( s t r ) → ( ι ∗ , π ∗ ) ∧ ι ∗ ∉ L : V r f y ( s t r , ι ∗ , π ∗ ) → 1 ] ≤ n e g l ( λ ) 。 \mathrm{Pr} [ str \gets \mathsf{Setup}(1^\lambda) \land \mathscr{A}_{\mathcal{P}^*}(str) \to (\iota^*, \pi^*) \\ \land \iota^* \notin L : \mathsf{Vrfy}(str, \iota^*, \pi^*) \to 1 ] \leq \mathsf{negl}(\lambda)。 Pr[str←Setup(1λ)∧AP∗(str)→(ι∗,π∗)∧ι∗∈/L:Vrfy(str,ι∗,π∗)→1]≤negl(λ)。
( P ∗ \mathcal{P}^* P∗右上角带星号代表它是恶意的, A \mathscr{A} A是敌手Adversary或Algorithm的缩写, A P ∗ ( s t r ) \mathscr{A}_{\mathcal{P}^*}(str) AP∗(str)表示 P ∗ \mathcal{P}^* P∗将 s t r str str作为输入参数运行算法 A P ∗ \mathscr{A}_{\mathcal{P}^*} AP∗)
自适应零知识性,由于 ι \iota ι本身是NP语句, V \mathcal{V} V难以从 ι \iota ι中学习 ω \omega ω的相关知识,此外,我们期望 P \mathcal{P} P与 V \mathcal{V} V的交互脚本(transcript)不会进一步泄露 ω \omega ω的相关知识,这里通过模拟器 S i m = ( S i m 1 , S i m 2 ) \mathsf{Sim} = ( \mathsf{Sim}_1, \mathsf{Sim}_2 ) Sim=(Sim1,Sim2)来刻画该性质( V ∗ \mathcal{V}^* V∗即使不与 P \mathcal{P} P交互,也可以得到一组“合法”的脚本,“合法”指的是模拟脚本与真实脚本在 V ∗ \mathcal{V}^* V∗看来不可区分),
P r [ s t r ← S e t u p ( 1 λ ) : A V ∗ P r o v e ( s t r , ι , ω ) ( s t r ) → 1 ] − P r [ ( s t r , t d ) ← S i m 1 ( 1 λ ) : A V ∗ S i m 2 ( s t r , t d , ι ) ( s t r ) → 1 ] ≤ n e g l ( λ ) 。 \mathrm{Pr} [ str \gets \mathsf{Setup}(1^\lambda) : \mathscr{A}_{\mathcal{V}^*}^{\mathsf{Prove}(str, \iota, \omega)}(str) \to 1] \\ -\mathrm{Pr}[ (str, td) \gets \mathsf{Sim_1}(1^\lambda) : \mathscr{A}_{\mathcal{V}^*}^{\mathsf{Sim}_2(str,td, \iota)}(str) \to 1 ] \leq \mathsf{negl}(\lambda)。 Pr[str←Setup(1λ):AV∗Prove(str,ι,ω)(str)→1]−Pr[(str,td)←Sim1(1λ):AV∗Sim2(str,td,ι)(str)→1]≤negl(λ)。
知识论证性质,若 P ∗ \mathcal{P}^* P∗没有相关证据 ω ∗ \omega^* ω∗,那么它针对论断 ι ∗ \iota^* ι∗(s.t. C h e c k ( s t r , ι ∗ , ω ∗ ) = 1 \mathsf{Check}(str, \iota^*, \omega^*)=1 Check(str,ι∗,ω∗)=1)生成一个有效的证明 π ∗ \pi^* π∗的概率为可忽略函数,这里通过提取器 E x t = ( E x t 1 , E x t 2 ) \mathsf{Ext} = (\mathsf{Ext}_1, \mathsf{Ext}_2) Ext=(Ext1,Ext2)来刻画该性质(若 P ∗ \mathcal{P}^* P∗成功伪造一个证明 π ∗ \pi^* π∗,则 E x t \mathsf{Ext} Ext可以成功从中提取出 ω ∗ \omega^* ω∗,这与 P ∗ \mathcal{P}^* P∗不知道 ω ∗ \omega^* ω∗的前提相矛盾),
∣ P r [ s t r ← S e t u p ( 1 λ ) : A P ∗ ( s t r ) → 1 ] − P r [ ( s t r , t d ) ← E x t ( 1 λ ) : A P ∗ ( s t r ) → 1 ] ∣ ≤ n e g l ( λ ) , \Big| \mathrm{Pr} [ str \gets \mathsf{Setup}(1^\lambda) : \mathscr{A}_{\mathcal{P}^*} (str) \to 1 ] \\ -\mathrm{Pr} [ (str, td) \gets \mathsf{Ext}(1^\lambda) : \mathscr{A}_{\mathcal{P}^*} (str) \to 1 ] \Big| \leq \mathsf{negl}(\lambda), ∣∣∣Pr[str←Setup(1λ):AP∗(str)→1]−Pr[(str,td)←Ext(1λ):AP∗(str)→1]∣∣∣≤negl(λ),
且
P r [ ( s t r , t d ) ← E x t 1 ( 1 λ ) ∧ A P ∗ ( s t r ) → ( ι ∗ , π ∗ ) ∧ V r f y ( s t r , ι ∗ , π ∗ ) → 1 ∧ E x t 2 ( s t r , t d , ι ∗ , π ∗ ) → ω ∗ : C h e c k ( ι ∗ , ω ∗ ) = 0 ] ≤ n e g l ( λ ) . \mathrm{Pr} [ (str, td) \gets \mathsf{Ext}_1(1^\lambda) \land \mathscr{A}_{\mathcal{P}^*} (str) \to (\iota^*, \pi^*) \land \mathsf{Vrfy} (str, \iota^*, \pi^*) \to 1 \\ \land \mathsf{Ext}_2 (str, td, \iota^*, \pi^*) \to \omega^* : \mathsf{Check} (\iota^*, \omega^*) = 0 ] \leq \mathsf{negl} (\lambda). Pr[(str,td)←Ext1(1λ)∧AP∗(str)→(ι∗,π∗)∧Vrfy(str,ι∗,π∗)→1∧Ext2(str,td,ι∗,π∗)→ω∗:Check(ι∗,ω∗)=0]≤negl(λ).
这里证明者Alice欲向验证者Bob证明它知道 y y y的离散对数解 x x x的具体值,双方运行如上 Σ \Sigma Σ协议。
正确性:
g z = g r + c x = ( g r ) ( g x ) c = a y c 。 g^z = g^{r + cx} = {(g^r)(g^x)}^c = ay^c。 gz=gr+cx=(gr)(gx)c=ayc。
零知识性质:模拟器 S i m \mathsf{Sim} Sim构造如下:
S i m : = z ← Z q c ← Z q a = g z / y c \begin{aligned} \mathsf{Sim} := & \\ & z \gets \mathbb{Z}_q \\ & c \gets \mathbb{Z}_q \\ & a = g^z / y^c \end{aligned} Sim:=z←Zqc←Zqa=gz/yc
模拟器输出的脚本 ( a , c , z ) (a, c, z) (a,c,z)与运行协议产生的真实脚本 ( a , c , z ) (a, c, z) (a,c,z)不可区分。
知识论证性质:可以这样子想象, P ∗ \mathcal{P}^* P∗持有算法 A P ∗ \mathscr{A}_{\mathcal{P}^*} AP∗却不知道 ω ∗ \omega^* ω∗的值,它生成初始参数 a a a,然后接收挑战参数 c c c,设置程序断点,运行 A P ∗ \mathscr{A}_{\mathcal{P}^*} AP∗得到对应的 z z z,此时 P ∗ \mathcal{P}^* P∗将程序回滚至断点处,接收新的挑战参数 c ′ c' c′,运行 A P ∗ \mathscr{A}_{\mathcal{P}^*} AP∗得到对应的 z ′ z' z′,存在
g z = a y c , g z ′ = a y c ′ , g^z = a y^c, g^{z'} = a y^{c'}, gz=ayc,gz′=ayc′,
易求
x = ( z − z ′ ) ( c − c ′ ) − 1 mod q , x = (z - z')(c - c')^{-1} ~ \text{mod} ~ q, x=(z−z′)(c−c′)−1 mod q,
正常 Σ \Sigma Σ协议运行,一个诚实的证明者 P \mathcal{P} P是不允许程序回滚的,否则 ω \omega ω就泄露了,然而上述证明中证明者 P ∗ \mathcal{P}^* P∗是恶意的,它自己可能也好奇 ω ∗ \omega^* ω∗的具体值,因此接受程序回滚(或者说整个协议都是它自己在运行),最后求出 ω ∗ \omega^* ω∗的值,这与它不知道 ω ∗ \omega^* ω∗的值的前提相矛盾。
扩展阅读:Nils Fleischhacker, Johannes Krupp, Giulio Malavolta, Jonas Schneider, Dominique Schröder, and Mark Simkin. Efficient unlinkable sanitizable signatures from signatures with re-randomizable keys. In Public Key Cryptography, pages 301–330, Taipei, Taiwan, 6-9 March 2016. Springer, Berlin.
该 Σ \Sigma Σ协议可用于证明Prover知道某消息 m m m的RSA签名。正确性、零知识性质、知识论证性质证明请自行证明。
前驱知识参考资料:
Jonathan Katz and Yehuda Lindell. Introduction to modern cryptography. CRC press, Boca Raton, 2014.
Katz J. Digital signatures[M]. [S.l.]: Springer Science & Business Media, 2010.
Alice欲向Bob证明她知道打开环形隧道中间石门的神秘咒语,但又不能将咒语泄露给Bob。整个协议运行如下,在Alice进入隧道后,Bob随机喊出一个方向A或B(挑战值),接着Alice从该方向走出来。若Alice一开始从A方向进入,而Bob喊出B方向,除非Alice真的知道神秘咒语 ω \omega ω,否则她不能从B方向出来。若Alice不知道 ω \omega ω,则每次挑战,她成功忽悠Bob的概率为 0.5 0.5 0.5,即Alice从A(B)方向进入,而Bob恰巧喊出同方向A(B)。协议运行 λ \lambda λ轮,Alice每次都成功忽悠Bob的概率为 0. 5 λ 0.5^\lambda 0.5λ,为可忽略函数。
该协议的零知识性质易证明,注意,Bob一开始是不知道Alice进入隧道的方向的,模拟器 S i m \mathsf{Sim} Sim的输出可以是 ( A , A , A ) (A, A, A) (A,A,A)或 ( B , B , B ) (B, B, B) (B,B,B),这与真实脚本不可区分。若Bob一开始就知道Alice进入隧道的方向,那么模拟器 S i m \mathsf{Sim} Sim则不存在(此时,真实脚本要么是 ( A , B , B ) (A, B, B) (A,B,B),要么是 ( B , A , A ) (B, A, A) (B,A,A),与模拟脚本可区分)。
该协议的知识论证性质同样易证明。
在章节2.3“开启石门的神秘咒语”例子中,Bob与Alice之间需要进行 λ \lambda λ轮交互,增加了通信开销和计算开销(注意密码学意义上的随机数生成算法计算开销较大),于是,后来有了非交互式零知识证明(Non-Interactive Zero-Knowledge Proof,简称NIZK)。
这里仅简单介绍随机谕言机模型(Random Oracle,简称RO)下的NIZK怎么设计,以Schnorr’s Protocol为例,验证者Bob先编码出一个性质足够好的哈希函数 H \mathsf{H} H,将其发送给证明者Alice,Alice随机挑选 r ← Z q r \gets \mathbb{Z}_q r←Zq并计算 a : = g r mod q a := g^r ~ \text{mod} ~ q a:=gr mod q,运行 c : = H ( a ∥ y ) c := \mathsf{H}(a \| y) c:=H(a∥y)生成挑战 c c c,然后计算 z : = r + c ⋅ x z := r + c \cdot x z:=r+c⋅x,将证明 π : = ( a , z ) \pi := (a, z) π:=(a,z)发送给验证者Bob,该过程在生成挑战值 c c c阶段就无需与Bob交互。
这里的 H \mathsf{H} H被当成随机谕言机使用。注意,当 H \mathsf{H} H直接使用 S H A 256 \mathsf{SHA256} SHA256等实例化时,NIZK in RO的零知识性质无法证明过去(随机谕言机的重编码性reprogram无法体现),接下来是个人的观点, H \mathsf{H} H应该是具有以下性质的哈希函数:(1)Verifier要保证给定一个输入 a ∥ y a \| y a∥y哈希函数 H \mathsf{H} H的输出足够随机,使得其分布与 c ← Z q c \gets \mathbb{Z}_q c←Zq无异,从而使得Prover无法伪造证明;(2)Verifier无法有效说服众人 H \mathsf{H} H没有后门,即众人怀疑Verifier在编码 H \mathsf{H} H时有可能故意先计算 z ← Z q z \gets \mathbb{Z}_q z←Zq、 c ← Z q c \gets \mathbb{Z}_q c←Zq和 a : = g z / y c a := g^z / y^c a:=gz/yc,并故意令 H ( a ∥ y ) = c \mathsf{H}(a \| y) = c H(a∥y)=c,但Verifier无法有效反驳该观点(当Prover意识到Verifier能够有效反驳该观点时,Prover应该立即拒绝给出证明 π \pi π)。
想象一个极端例子, y y y的离散对数答案 x x x超级值钱,Alice拟向Bob炫耀她知道 x x x的值,运行NIZK in RO,若 H \mathsf{H} H的输出不够随机,那么Alice有可能找到一组特别的模拟脚本 ( a , c , z ) (a, c, z) (a,c,z)恰巧对应 H \mathsf{H} H的输入和输出,以此来欺骗Bob;若 H \mathsf{H} H完全没有后门,Bob有可能起嫉妒心,向强盗透露Alice知道 x x x的值,从而使得Alice遭到追杀。
如何构造这样一个 H \mathsf{H} H函数,接下来纯粹是个人想法:将 a ∥ y a\|y a∥y输入到 S H A 256 \mathsf{SHA256} SHA256中得到哈希值 h h h,将该哈希值 h h h映射到 Z q \mathbb{Z}_q Zq的元素 c c c上,这张映射表由Verifier编码,从而实现重编码性。由于 S H A 256 \mathsf{SHA256} SHA256被当成RO来用,即使映射表固定, H \mathsf{H} H的输出对于Prover来说是随机的。
例如,在章节2.3“开启石门的神秘咒语”例子中,假设原先交互 k k k轮,现Verifier对 H \mathsf{H} H的编码为 H : = ( S H A 256 , 映 射 表 1 , 映 射 表 2 , … , 映 射 表 k ) \mathsf{H}:=(\mathsf{SHA256}, 映射表1, 映射表2, \dots, 映射表k) H:=(SHA256,映射表1,映射表2,…,映射表k);在章节2.1“Schnorr’s Protocol”例子中,若 Z q \mathbb{Z}_q Zq有1024bit,而SHA256有256bit,则使用4个带秘钥的SHA256来实现1024bit。映射表可以编码成1、2、3等形式,表示向下循环移位1个元素、2个元素、3个元素等。