这篇文章首发于知乎专栏:https://zhuanlan.zhihu.com/p/87900715
这篇论文在2018年发表在顶会NSDI上面,题目为《zkLedger: Privacy-Preserving Auditing for Distributed Ledgers》,作者为Neha Narula, MIT Media Lab; Willy Vasquez, University of Texas at Austin; Madars Virza, MIT Media Lab。
作者在NSDI上面做了演讲,通过下面这个链接可以查看演讲视频,演讲使用的PPT以及论文。在论文里面还可以找到论文实现源码。本人看这篇论文的时候,卡在了关键的部分,最后是结合了论文源码才看懂的。如果你对源码有问题的话,可以在下面留言。作者演讲所使用的PPT虽然简单易懂,但是太笼统了。
zkLedger: Privacy-Preserving Auditing for Distributed Ledgerswww.usenix.org
论文问题定义
银行的交易账本被审计的时候,银行希望不泄露:
- 交易的对象信息
- 每一条交易的具体金额
- 交易图谱(transaction graph)(即不能通过关联多条交易来挖掘出私密信息)
满足上面条件的情况下,能够做到基本的审计功能有:
- 某一个银行在某一时刻拥有多少资产?(最基本的功能)
- 某一个银行平均每一个交易的数额?
- 某一个银行所有交易金额的标准差是多少?
上面便是本文所要解决的问题了。在我们进一步了解之前,有必要知道一点点密码学的知识,这里简单整理和介绍一下。
背景知识
----------------------start---------虚线里面的内容可以跳过---------------------
群 Group,满足下面四个特性
- 1 封闭性(closure):如果a和b被包含于G ,那么a+b 也一定是G的元素。
- 2 结合律(associativity)。
- 3 存在一个单位元(identity element)0,使得 a+0 = 0+a = a;[单位元:与任意元素运算不改变其值的元素]
- 4 每个数都存在一个相反数(inverse)。
阿贝尔群(abelian group),在群的基础之上满足下面特性
- 5 交换律(commutativity): a+b = b+a.
我们可以在椭圆曲线定义一个群,其中一条椭圆曲线就是一组被 y^2=x^3+ax+b定义的且满足 4a^3+27b^2≠0 的点集。使用该曲线实现椭圆曲线加密算法Elliptic Curve Cryptography(ECC)。
上图表示如何在椭圆曲线上面定义加法和乘法。左边的图中,P和Q是曲线上面的一个点,R点是交点关于x轴对称的点,得到P+Q = R。中间的图,P点是一个切点,表示两个P相加。对于右图,先计算P+P = 2P,再计算2P+P = 3P,这样子就可以推导出椭圆曲线上面的乘法了。本论文中主要使用到了乘法。
-----------------------------------------end------------------------------------
使用ECC如何根据私钥x生成公钥呢?
私钥公钥生成:?k=?∗?
其中pk 是公钥,x是私钥,G是椭圆曲线上的一个点。特点是,知道x和G,容易计算出pk;知道pk和G,难计算出x。
同时,它有一个特别重要的特性,那就是它满足交换律和结合律
v1*G + v2*G = (v1 + v2)*G
使用上面的等式的特性,我们得出重要的Pedersen Commitment,形式为
(v1*G + r1*H) + (v2*G + r2*H) = v3*G + r3*H
其中v3 = v1 + v2; r3 = r1 + r2。G和H是椭圆曲线上面的两个不同的点,v和r是数值标量(scalar)。
例子 : (6*G + 222222222222*H) + (3 * G + 444444444444 * H) = 9 * G + 666666666666 * H。其中6和3可以表示为交易金额(私密信息), 222222222222和444444444444是致盲因子。这样就能够让审计者不知道具体交易数据的情况下验证交易成立:只需要告诉审计者9和666666666666.。MimbleWinble协议使用到了Pedersen Commitment,来隐藏区块链中用户交易金额和交易图谱,达到隐私保护的作用。MimbleWinble协议有Grin和Beam两个实现,具体可以了解一下。下面两张图片是Bean一个交易数据的截图,可以发现一个交易的inputs和outputs都是字符串,实际的交易对象和交易金额都被隐藏了。
下面的一张图是比特币的一个交易数据,其中的交易对象的地址和交易金额是公开的。这些是题外话了。下面进入正题。
系统设计
总共有三个主体对象,分别是银行,账本和审计员。前两者有自己的本地数据库,存储自己的私密信息。三者通过分布式账本连在一起。
账本中的隐私交易数据被隐藏了,使用transaction commitment和proof来代替。如下图,所有的银行都对应着表格的一列,一行数据表示一个交易,一个交易的所有交易数据都是由该交易的发起者构造和生成的,交易的接收者和交易无关这不需要构造这一行数据,但是每一行单元格都需要被填写,即使该银行是该交易的无关者。下图中,bank1向bank2转账10^6欧元,bank1的值为-10^6,bank2的值为10^6。其它也有相应的数据,其交易金额为0。这样子就可以隐藏交易的参加者了。
如何审计一个银行当前的资产呢?先讲基本的方法,然后再将改进的方法。
第一种方法:
根据Pedersen Commitment, 可以构造这样的等式,(v1*G + r1*H) + (v2*G + r2*H) +…+ (vn*G + rn*H)= v3*G + r3*H
即
其中 ,
,m表示从开始到当前某个银行的所有交易数量,vi表示第i交易的数额,ri表示第i交易的致盲因子(或者说密钥)。
审计员知道该银行每条交易的commitment(从账本中),以及该银行当前资产数v3(银行告诉的)和致盲因子之和r3(银行告诉的)审计员验证等式: ,
如果等式成立,表示该银行的账单没问题。
但是,账单表格中的每一行数据是由该交易的发起者构建生成的,其它银行是不知情的,也就是每一个单元格中的 致盲因子 只有该行交易的发起者知道。这就有问题了,因为根据上面所述的方法,在审计员审计一个银行的时候,需要该银行提供给审计员
。怎么解决这个问题呢?可不可以绕开致盲因子ri呢?为了解决这个问题,提出了第二种方法。
第二种方法
- 在每一个单元格中增加一个Token,计算方法为
, 其中pk是椭圆曲线上一个点,也是第i银行的公钥,ri表示致盲因子(椭圆曲线算法)。根据Pedersen Commitment,有
所以
,
发现可以从账本中计算到 ,可以从被审计的银行那里得到
,也就是我们可以绕开
来计算
的值。
令 ,两边做椭圆曲线乘法运算,乘以x,得到
(1)
已知一个单元格的Token表示为 ,我们又知道通过私钥生成公钥的计算公式为:
(2)
其中 表示被审计的银行的公钥。所以,某一银行所在列的所有Token的和为
(3)
根据(1)(3)式,发现 (4)
现在,在(2)(4)式子中,除了x,其它所有变量的值都可以计算的得到,最后,通过非交互式零知识证明,证明(2)(4)两式所使用的x是相等的。如果证明为真,审计通过,表示该银行当前拥有 的资产。
小结一下:第二种方法中,被审计的银行只需要向审计员提供 的值即可,不需要提供
的值。
一致性证明 ![[公式]](https://i-blog.csdnimg.cn/blog_migrate/1dc060f5942fc9819ab32b2950270756.png)
上面的证明是基于一个假设前提, 和
使用的是相同的ri。所以,我们要让交易发起者在构造数据的时候,保证使得两个ri相等。但是我们不信任他,因此我们要求他构造一个一致性证明(proof of consistency),表示为
,并把这个证明保存到每一个单元格中,以便让其它用户认证:如果通过,表示两个式子中的ri是相等的。
具体怎么构造这个零知识证明中的一致性证明,可以参考相关论文,或者查看论文实现源码。
其它零知识证明
- 资产证明
proof of assets, 用来证明这个银行在某一时刻有某数量的资产。
- 范围证明Range Proof
用来证明交易金额在一定的范围内,比如大于0.这里还涉及到造币和毁币的问题,具体这里不深入。在本论文中,每一个单元格都需要这个证明。
- Proof of Balance
来证明一个转账交易的所有数额之和为0, ,付款者资产减少,收款者资产增加,总和为0.
谢谢!