本文已更新至Githubhttps://github.com/sec-bit/learning-zkp/blob/master/zkp-intro/3/zkp-pok.md
导言:有些理论非常有趣,零知识证明便是其中之一,摸索了许久,想写点什么,与大家一起讨论。本文是『探索零知识证明』系列的第三篇。全文约 7,000 字,少量数学公式。
And what, Socrates, is the food of the soul? Surely, I said, knowledge is the food of the soul.
苏格拉底,什么是灵魂的食物?我说过,当然是知识。
—— 柏拉图
「零知识」vs. 「可靠性」
我们在许多介绍零知识证明的文章中都能看到这样三个性质:
- Completeness —— 完备性
- Soundness —— 可靠性
- Zero-Knowledge —— 零知识
但是少有文章深入解释这个特性背后的深意和洞见。
在『系列(二)理解「模拟」』一文中,我们介绍了「模拟器」这个概念。许多介绍文章避而不谈「模拟」,但「模拟」可以说是安全协议中核心的核心,因为它是定义「安全性」的重要武器。
通常,我们定义安全会采用这样一种方式,首先列出一些安全事件,然后说明:如果一个系统安全,那么列出来的安全事件都不会发生。
Rather than giving a list of the events that are not allowed to occur,it (the definition of zero-knowledge proof) gives a maximalist simulation condition.
— Boaz Barak
借用密码学家 Boaz Barak 的话,翻译一下,「零知识证明」并不是通过给出一个不允许发生的事件列表来定义,而是直接给出了一个最极致的「模拟条件」。
所谓「模拟条件」是指,通过「模拟」方法来实现一个「理想世界」,使之与「现实世界」不可区分;而由于在理想世界中不存在知识,所以可以推导出结论:现实世界满足「零知识」。
我们继续分析下一个交互系统(安全协议)的三个性质:「完备性」、「可靠性」与「零知识」。
可靠性(Soundness):Alice 在没有知识的情况下不能通过 Bob 的验证。
完备性(Completeness):Alice在有知识的情况下可以通过 Bob 的验证。
零知识(Zero-knowledge):Alice 在交互的过程中不会泄露关于知识的任何信息。
我们可以看出来「可靠性」和「完备性」有一种「对称性」。可靠性保证了恶意的 Alice 一定失败,而完备性保证了诚实的 Alice 一定成功。
「完备性」比较容易证明,只要 Alice 诚实,Bob 也诚实,那么皆大欢喜。这好比,写好一段代码,喂了一个测试用例,跑完通过收工。
我们来想想「可靠性」应该如何定义?这个可靠性的逆否命题是:(在现实世界中)如果 Alice 能通过 Bob 的验证,那么 Alice 一定有知识。或者说:Alice 知道那……个「秘密」!
下面的问题是如何证明 Alice 知道一个「秘密」?
这好像也很难,对不对?假如我们需要证明一台机器知道一个「秘密」,最简单的办法就是我们在机器的硬盘里,或者内存中找到这个「秘密」,但是这样暴露了秘密。如果这台机器是黑盒子呢?或者是 Alice 呢?我们没有读心术,猜不到她心里的那个秘密。
如何定义「To Know」?
「零知识」保证了 验证者 Bob 没有(计算)能力来把和「知识」有关的信息「抽取」出来。不能抽取的「知识」不代表不存在。「可靠性」保证了知识的「存在性」。
只有「知识」在存在的前提下,保证「零知识」才有意义
本文将探讨「可靠性」和「To Know」。
为了进一步分析「知识」,接下来首先介绍一个非常简洁,用途广泛的零知识证明系统 —— Schnorr 协议。这个协议代表了一大类的安全协议,所谓的 Σ-协议,而且 Schnorr 协议扩展也是 零知识数据交换协议 zkPoD [1] 的核心技术之一。
简洁的 Schnorr 协议
Alice 拥有一个秘密数字,a,我们可以把这个数字想象成「私钥」,然后把它「映射」到椭圆曲线群上的一个点 a*G,简写为 aG。这个点我们把它当做「公钥」。
- sk = a
- PK = aG
请注意「映射」这个词,我们这里先简要介绍「同态」这个概念。椭圆曲线群有限域之间存在着一种同态映射关系。有限域,我们用 Zq这个符号表示,其中素数 q是指有限域的大小,它是指从 0, 1, 2, …, q-1 这样一个整数集合。而在一条椭圆曲线上,我们通过一个基点,G,可以产生一个「循环群」,标记为 0G, G, 2G, …, (q-1)G,正好是数量为 q个 曲线点的集合。任意两个曲线点正好可以进行一种「特殊的二元运算」,G + G = 2G,2G + 3G = 5G,看起来这个二元运算好像和「加法」类似,满足交换律和结合律。于是我们就用 +这个符号来表示。之所以把这个群称为循环群,因为把群的最后一个元素 (q-1)G,再加上一个 G就回卷到群的第一个元素 0G。
给任意一个有限域上的整数 r,我们就可以在循环群中找到一个对应的点 rG,或者用一个标量乘法来表示 r*G。但是反过来计算是很「困难」的,这是一个「密码学难题」—— 被称为离散对数难题[2]。
也就是说,如果任意给一个椭圆曲线循环群上的点 R,那么到底是有限域中的哪一个整数对应 R,这个计算是很难的,如果有限域足够大,比如说 256bit 这么大,我们姑且可以认为这个反向计算是不可能做到的。
Schnorr 协议充分利用了有限域和循环群之间单向映射,实现了最简单的零知识证明安全协议:Alice 向 Bob 证明她拥有 PK 对应的私钥 sk。