Schnorr's Protocol, A ZK Proof for Dlog (Prove You Know Your Private Key)

Table of Contents

1. 背景介绍

在设计基于公钥密码体系的协议时,有下面原则:

Do not assume that a message you receive has a particular form (such as g^r for known r) unless you can check this.

这个原则是 1995 年 Anderson, R. 和 R. Needham 在论文 Robustness Principles for Public Key Protocols 中提出的 8 个原则中的第 6 个原则。

问: Prover A 提供了公钥 \(y\) 给 Verfier B,在不泄露私钥 \(x\) 情况下,Prover A 如何向 Verfier B 证明他所提供的数据 \(y\) 确实是他所掌握(掌握在此意思是知道其对应的私钥)的一个公钥。 这就是本文所探讨的主题。注:通过签名显然可以实现这个任务,不过签名本身是一个复杂协议,它比后文所讨论的内容要复杂得多。

1.1. Rogue Key Attack

上面提到, 一个协议的某参与者如果需要发送其公钥给其它人时,那么这个参与者需要证明他掌握这个公钥对应的私钥。否则,这个协议可能不安全。 是否有例子来说明这种不安全性呢?答案是有的,比如 Rogue Key Attack

下面以 Schnorr 多签协议的例子来说明一下 Rogue Key Attack。假设 Alice 和 Bob 要组成 2-2 Schnorr 多签协议,协议的大概流程是,Alice 把她的公钥 \(Q_A = s_A \cdot G\) 发送给 Bob,而 Bob 也把他的公钥 \(Q_B = s_B \cdot G\) 发送给 Alice,这样它们两个人对外的共同公钥是 \(Q = Q_A + Q_B = (s_A + s_B ) \cdot G\) ,共同私钥是 \(s_A + s_B\) 。

如果协议中没有要求 Alice/Bob 提供证明,来证明他们分别知道其对应的私钥(即 \(s_A\) 和 \(s_B\) ),则这个协议有安全问题。比如 Bob 作恶,发送给 Alice 的公钥并不是 \(Q_B\) ,而是把 \(Q_B - Q_A\) 发送给 Alice,这样,算出来的共同公钥就是 \(Q_A + (Q_B - Q_A) = Q_B\) 了,从而 Bob 一个人就掌握了这个共同公钥背后的私钥 \(s_B\) 了。

如果要求 Bob 证明他知道他所提交的公钥所对应的私钥,则上面的 Rogue Key Attack 就可以避免,因为 \(Q_B - Q_A\) 所对应的私钥为 \(s_B - s_A\) ,Bob 不知道 Alice 的私钥 \(s_A\) ,显然 Bob 无法证明他知道 \(s_B - s_A\) 。

2. Interactive Schnorr Protocol (Three-Pass)

Schnorr 提出了一个交互式的协议(被 Schnorr 命名为 “Identification Protocol”)解决了上节提出的问题。这个协议在 Schnorr 的下面两篇论文中都有描述:

2.1. 形式一:DSA 公私钥

假设 DSA 参数分别为 \((p,q,g)\) ,其中 \(p,q\) 是大素数,且满足 \(q \mid p-1\) ,私钥 \(x\) 为 \(\{1,2,\cdots,q-1\}\) 中随机数,公钥为 \(y=g^x \bmod p\) 。

通过下面的 3 趟交互过程,Prover A 可以向 Verfier B 证明他确实知道 \(y\) 对应的私钥 \(x\) ,这个过程没有泄露私钥 \(x\) 。

Schnorr's Protocol:

        Prover A                                       Verfier B
--------------------------                     --------------------------

从 [1,q-1] 中选择随机数 r
计算 t = g^r mod p                --- t --->


                                  <-- c ----     选择随机数 c


计算 z = r + c x mod q            --- z --->      验证:g^z = t * y^c mod p 是否成立?

最后一步,如果 Verfier B 验证 \(g^z = t * y^c \bmod p\) 成立,则说明 Prover A 确实知道 \(y\) 对应的私钥 \(x\) 。这是因为:
\[\begin{aligned} g^z &= g^{r+cx} \\ &= g^r \cdot g^{cx} \\ &= t \cdot (\boldsymbol{g^x})^c \\ &= t \cdot \boldsymbol{y}^c \end{aligned}\]

2.1.1. Schnorr Protocol 属于“零知识协议”

Schnorr 协议属于“零知识协议”,也就是说在证明过程中 Prover 没有泄露关于私钥的任何信息。如何证明呢 Prover 确实没有泄露关于私钥的信息呢?

采用“Simulation-Based Security”模型,Simulator 在不知道私钥的情况下,如果可找到一个算法可以骗过 Verfier(这样的算法确实可找到,如图 1 所示,摘自 https://www.youtube.com/watch?t=480&v=_YpGx_nLJow ),则 Schnorr 协议具备“Simulation-Based Security”。对此有疑问的读者可以查阅 Simulation-Based Security 的相关资料。

schnorr_zkp.gif

Figure 1: Simulator 算法 \(\mathcal{S}\) (记号和前文有区别)

2.2. 形式二:椭圆曲线公私钥

假设椭圆曲线,某私钥 \(d\) 为 \(\{1,2,\cdots,n-1\}\) 中随机数,公钥为 \(Q =d G\) 。

通过下面的 3 趟交互过程,Prover A 可以向 Verfier B 证明他确实知道 \(Q\) 对应的私钥 \(d\) ,这个过程没有泄露私钥 \(d\) 。

Schnorr's Protocol:

        Prover A                                       Verfier B
--------------------------                     --------------------------

从 [1,n-1] 中选择随机数 r
计算 T = r G                      --- T --->


                                  <-- c ----     选择随机数 c


计算 z = r + c d mod n            --- z --->      验证:T = z G - c Q 是否成立?

2.3. Sigma Protocols

Schnorr Protocol 是一种 Sigma Protocols,形如图 2(摘自:A Graduate Course in Applied Cryptography, by Dan Boneh and Victor Shoup)所示的协议都是 Sigma Protocols。

schnorr_sigma.gif

Figure 2: Execution of a Sigma protocol

一个 Sigma Protocol 共有 3 趟,3 趟所发的消息分别为 commitment、challenge、response。 之所以称为“Sigma Protocols”,这是因为希腊字母 \(\Sigma\) 的写法和交互流程有点像。

3. Non-Interactive Zero Knowledge (NIZK)

通过 Fiat-Shamir Transform 可以把“交互式”协议改为“非交互式”协议。

具体对于 Schnorr 协议来说,就是 把 Verfier 发送给 Prover 的 Challenge 数字 \(c\) 换为一个随机函数,如 \(H(g, y, t)\) (计算哈希时也可以把 Prover 的 ID 加上,如 \(H(g,y,t,ProverUID)\) ),从而 Schnorr 协议变为了非交互式地(Non-Interactive)。由于 \(g,y,t\) 都是公开的,从而所有人都可以计算 \(H(g,y,t)\) ,所有人都可以进行验证。

4. 扩展阅读:证明你知道 RSA(或 Paillier)私钥

使用 Schnorr Protocol,用户可以证明他知道某个 DSA(或者椭圆曲线)公钥所对应的私钥。DSA(或者椭圆曲线)这类公私钥是基于“离散对数”难题的,所以 Schoor Protocal 是一种 Zero-Knowledge Proofs for Discrete Logs (Dlog)。

还有一类基于“整数因子分解”难题的公私钥,如 RSA、Paillier 等。对于这类公私钥,用户如何证明他知道某个公钥所对应的私钥呢?这里不详细介绍,可以参考下面文献:
Short Proofs of Knowledge for Factoring, Guillaume Poupard and Jacques Stern, 2000
Efficient Noninteractive Certification of RSA Moduli and Beyond, Sharon Goldberg, Leonid Reyzin, Omar Sagga and Foteini Baldimtsi, 2019

5. 参考

Author: cig01

Created: <2020-11-13 Fri>

Last updated: <2021-01-11 Mon>

Creator: Emacs 27.1 (Org mode 9.4)