上交所技术公司 朱立
先复制一小段项目简介:
zkLedger的文章在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。文章附带一个go的实现,开源在了github上。
论文问题定义
银行的交易账本被审计的时候,银行希望不泄露:
交易的对象信息
每一条交易的具体金额
交易图谱(transaction graph)(即不能通过关联多条交易来挖掘出私密信息)
满足上面条件的情况下,能够做到基本的审计功能有:
某一个银行在某一时刻拥有多少资产?(最基本的功能)
某一个银行平均每一个交易的数额?
某一个银行所有交易金额的标准差是多少?
(复制结束,原创简书开始)
1) 确认zkLedger的设计有一个严重漏洞,会摧毁其可被审计性。退一步说,按现有的设计,做支付系统也是不行的。鉴于它的安全假设是每一个bank都可能作恶,而这里举出了一种他没有考虑到的作恶形式,因此可以确认是其漏洞。
要理解该漏洞,现需要理解原始论文的做法。原始论文没有对其中的零知识证明方式给出详细解释,本文的内容是根据其源码反推后整理出来的。懒得打字,给一个图吧,一目了然:
为了减少沟通成本,zkLedger的目前的设计是使参与者不必为交易合作构建证据,资金转出方可以单独创建交易,然后线下通知收款方多少金额。问题在于自己线下LOCAL维护的sum可能和实际的值不同——恶意攻击者在不通知你的情况下给你账户上加上1分钱,或者链外给你说得好好的给你转一个亿结果转入1分钱。如果不枚举去猜转入多少钱,就完全无法构造后续支付及审计所需的证明了。
为何无法构造后续支付和审计需要的证明,需要结合其验证逻辑和上述证明的运作原理去理解。产生证明的逻辑在bank.go中,验证逻辑在transaction.go中,查找verify函数即可。
论文中对转出者本列cm求和结果的range进行的零知识证明很聪明,是细节上的亮点。这个求和结果的random信息是不知道的,因此单纯知道v的和也不能open之,也实际上无法直接为之构造rangeproof证明。文中基于sum构建了cm',针对cm'提供rangeproof,再用cm'-cm,最终间接完成cm的rangeproof,非常巧妙。
2)改进后的方案 zkLedger++在这里:
结合zether回头写一篇东西。解决方案是2个方向:1) 学习ZETHER采用暴力枚举猜测自己的余额(当然对于2^40的可能空间,未免太暴力),
或者 2) 要求交易接收方也签名,构造一个3个可能性的disjunctive零知识证明:V>0, V=0, V < 0, 其中V不为0的情况都需要证明者(可能是转出方,可能是转入方)知道私钥,因此此时必然是协作构建交易的。这种 1 of n 的disjunctive 零知识证明是94年就被解决的问题,可以做出来?
上图有一个小错误(中间那种情况),图暂时没法修改,记录如下:
b1=cm' - SUM_COL(cm)
r1= rt' - SUM_COL(rt)
V<0 时候交易构建人只能用通过这个途径来符合要求,需要知道SK
V >0 时候交易构建人可以通过这个途径来符合要求,需要知道SK
b2=h
r2=cm
V = 0 的时候,交易构建人可以无需提供V=0者的私钥
b3 = cm' - cm,
r3 = rt' - rt
V > 0的时候,交易构建人可以通过这个途径来符合要求,需要知道SK
3) 上面新增的零知识证明可以形成完整的证据链
理解的时候把上面公式中的每个变量加上一个等于公式序号的下标,这样对于假设应该用同一个v的地方就出现了多个不同的变量vi,然后利用给出的一致性证明等去归约,证明相同的变量都改用同一个下标,如此直到最后就可以看出现在的零知识证明确实是完备的。
网友评论