-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
how to proof that prover owns a polynomial
- Loading branch information
Showing
1 changed file
with
80 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
--- | ||
layout: post | ||
title: "02-如何证明拥有一个多项式" | ||
categories: zkp | ||
tags: 原创 zkp groth16 | ||
author: fatcat22 | ||
mathjax: true | ||
--- | ||
|
||
* content | ||
{:toc} | ||
|
||
|
||
|
||
|
||
在[前一篇文章](https://yangzhe.me/2023/10/11/first-story-of-zk)的例子里,验证者要知道整个多项式才能验证,我们说了,这不算是「零知识」。那如何让产生多项式的证明者(prover)在不让任何人知道多项式的情况下,还能让验证者(verifier)进行验证呢?这篇文章我们来解决这个问题。 | ||
|
||
> 术语解释: | ||
> prover: 证明者。prover 拥有原始数据,并通过使用多项式的方式,隐藏原始数据。 | ||
> verifier: 验证者。对 prover 发起挑战,进行验证。 | ||
> | ||
>prover 和 verifier 是在提及零知识证明时,常用的指代产生证明和进行验证的双方的术语,后面我们也会使用这样的称呼,不再使用「证明者」或「验证者」这样的名称。 | ||
首先我不得不说,在 verifier 完全什么也不知道的情况下,让 verifier 去验证、然后还能验证成功,我觉得是不可能的。顺着这个思路往下想,那就变成了:我们得让 verifier 知道点什么,让 ta 可以根据知道的这点东西进行验证,但知道的这点东西又不足以让他知道事情的全貌。 | ||
具体来说,就是我们得让 verifier 知道 prover 拥有的多项式的一部分,让 ta 可以对多项式进行验证;但 verifier 知道的这部分多项式,不足以让 ta 推导出整个多项式来。 | ||
|
||
# 1. 拆分多项式 | ||
如何能把多项式的一部分给 verifier ,又不足以让 verifier 推导出整个多项式呢? | ||
## 1.1 加法拆分? | ||
多项式嘛,无非就是 $f(x)=a_nx^n + a_{n-1}x^{n-1}+...+a_3x^3+a_2x^2+a_1x+a_0$ ,如果我们把 $a_2x^2+a_1x+a_0$ 给 verifier ,剩下的部分 prover 自己留着,不就可以了嘛。我们形式化整理一下: | ||
令 | ||
|
||
$$\begin{align} | ||
h(x)&=a_nx^n + a_{n-1}x^{n-1}+...+a_3x^3 \\ | ||
t(x)&=a_2x^2+a_1x+a0 | ||
\end{align}$$ | ||
|
||
那么 $f(x)$ 就变成了: | ||
|
||
$$ | ||
f(x)=h(x)+t(x) | ||
$$ | ||
|
||
我们把 $t(x)$ 给 verifier ,在 $n$ 远大于 2 的情况下,只有 $t(x)$ verifier 肯定无法推导出整个多项式。那么验证过程就变成了: | ||
1. verifier 选择一个随机数 $s$ ,自己计算 $t(s)$ 后,将 $s$ 发给 prover。 | ||
2. prover 拿到 $s$ 后,分别计算 $f(s)$ 和 $h(s)$,并将 $f(s)$ 和 $h(s)$ 发给 verifier。 | ||
3. verfier 拿到 prover 返回的 $f(s)$ 和 $h(s)$ 后,验证 $f(s)=h(s)+t(s)$ 是否成立(注意这里的 $t(s)$ 是 verifier 自己算的)。如果成立,则验证成功。 | ||
|
||
就这? | ||
|
||
## 1.2 不,乘法拆分 | ||
差不多吧,上面我们的思路是对的,加法($f(x)=h(x) + t(x)$)也是最简单、我们最熟悉,最容易想出来的解决方法。但真正的零知识证明,其实用的是乘法,即 $f(x)=h(x)t(x)$ ,所以验证过程应该是: | ||
1. verifier 选择一个随机数 $s$ ,自己计算 $t(s)$ 后,将 $s$ 发给 prover。 | ||
2. prover 拿到 $s$ 后,分别计算 $t(s)$ 和 $h(s)$ ,并将 $f(s)$ 和 $h(s)$ 发给 verifier。 | ||
3. verfier 拿到 prover 返回的 $f(s)$ 和 $h(s)$ 后,验证 $f(s)=h(s)t(s)$ 是否成立(注意这里的 $t(s)$ 是 verifier 自己算的)。如果成立,则验证成功。 | ||
|
||
为什么要用乘法呢?因为这个验证过程实在太简单,漏洞百出,真正的零知识证明肯定不会这么简单。使用乘法,更有利于后面使用各种手段,补上这此「漏洞」,而加法,让这些手段无法施展。 | ||
|
||
你可能会产生一个疑问:$f(x)$ 变成 $h(x)+t(x)$ 显然易见,非常直观;但 $f(x)$ 肯定能变成 $h(x)t(x)$ 的方式吗? | ||
|
||
答案是肯定的,只要 prover 精心选择 $t(x)$ 。基础的线性代数理论告诉我们,如果 $a$ 是 $f(x)$ 的根,即 $f(a)=0$ ,那么 $f(x)$ 肯定能被 $(x-a)$ 整除;如果 $a$ 和 $b$ 都是 $f(x)$ 的根,那么 $f(x)$ 肯定能被 $(x-a)(x-b)$ 整除。 | ||
|
||
所以,我们只要找到 $f(x)$ 的几个根,比如两个,$a$ 和 $b$ ,令 $t(x)=(x-a)(x-b)$ ,那么 $f(x)$ 肯定能被 $t(x)$ 整除,得到 $h(x)$ 多项式。(当然你不能把 $f(x)$ 的所有根都放到 $t(x)$ 里,那样的话 $h(x)$ 就只能等于 1 了,并且 $t(x)$ 是要给 verifier 的,相当于把整个 $f(x)$ 直接暴露给了 verifier) | ||
|
||
这样,prover 就可以在不暴露整个多项式的情况下,让 verifier 进行验证了。 | ||
|
||
# 2. 总结 | ||
这篇文章主要解决一个问题:如何在让 verifier 不知道具体多项式是什么的情况下,prover 还可以证明自己有这样一个多项式。方法就是把 $f(x)$ 折成两部分:$h(x)t(x)$ ,其中 : | ||
- $t(x)=(x-a_1)(x-a_2)...(x-a_i)$ 。 $a_1,a_2,...,a_i$ 是 $f(x)$ 的 $i$ 个根,但不能是全部的根。假设 $f(x)$ 有 $n$ 个根,那么 $i$ 要远小于 $n$ | ||
- $h(x)=\frac{f(x)}{t(x)}$ | ||
|
||
到目前为止,除了「如何将一个问题转等价转换成多项式」这个问题,你已经基本掌握了零知识证明的精髓。 | ||
|
||
就这?你肯定会这么问。 | ||
|
||
「精髓」的意思是,它是事物的本质;但从另一个角度看,「精髓」需要依赖骨、肉等其它元素,才能组成一个完全的生命体。当你看到一个完整的生命体时,ta 呈现出来的肯定不是「精髓」的本来面目。 | ||
|
||
零知识证明的「精髓」就是 $f(x)=h(x)t(x)$ 。但直接使用它按着前面说的过程进行验证,依然是漏洞百出的。比如,当 prover 收到 verifier 的随机数 $s$ 时,由于 prover 知道 verifier 有 $t(x)$ ,也就当然知道 verifier 计算出来的 $t(s)$ 值,那么 prover 就可以随便调整 $f(x)$ 和 $h(x)$ 这两个多项式,比如调整为 $f'(x)$ 和 $h'(x)$ ,只要最终 $f'(s)=h'(s)t(s)$ 就可以了;把 $f'(s)$ 和 $h'(s)$ 发给 verifier ,依然可以通过验证(但实际上 prover 可能根本没有一个固定的多项式 $f(x)$ )。更甚至,prover 根本不需要多项式,ta 算出 $t(s)$ 的值后,随便选两个数 $m$ 和 $n$ ,只要满足 $m=nt(s)$ ,就可以把 $m$ 和 $n$ 发给 verifier ,依然能通过验证。 | ||
|
||
所以有了这个「精髓」还是不行的,后面要解决掉这些漏洞,让 prover 和 verifier 双方在完全不信任对方的情况下,依然能就某个问题达成一致(即 verifier 被说服。这就是零知识证明的用武之地,因为如果双方互相信任,也不用证明什么了,直接相信结果就得了)。可是如何做到呢?别着急,我们后面的文章会一一介绍。 |