零知识证明安全实现经验
1. 引言
JP Aumasson(BLAK hash function family论文的作者之一),在2022年的zkStudyClub中分享了其审计多个ZKP项目中发现的各种隐患和bug。
视频解说见:
- Zero Knowledge Summit Amsterdam 2022
主要关注的为:
- Fully succinct =O(1)=O(1)=O(1) proof size and O(circuit size)O(\text{circuit size})O(circuit size) verification time的zkSNARKs方案
主要基于审计以下项目的经验:
- Groth16:ZCash、Filecoin等。
- Marlin:Aleo使用的,为universal zkSNARKs。
这些经验也可用于其它如Plonk、SONIC、STARK等系统。
2. 为何需要学习zkSNARKs安全?
对于区块链项目,zkSNARKs的主要风险在于:
- 复杂性+创新性 会引起 non-trivial bugs
- 事关重大(很多钱$ 以及 用户数据和隐私)
作为一名密码学家,当今最有趣的密码:
- 解决现实世界问题,并大规模部署(好论文+好代码!)
- 具有重要组件的复杂结构
- “简单但复杂”(非交互式,很多moving部件)
- 关于安全的多维思考
3. 什么是zkSNARKs安全?
- 1)soundness,通常为实践中的最大风险:
- invalid proofs应总是被拒绝。
- 应无法伪造、修改、重放valid proofs。
- 2)Zero-knowledge:proofs不应泄露witness信息(私有变量)
- 实践中,large programs的succinct proof仅可泄露一点点数据。
- 3)Completeness:通常DoS/可用性风险可能会被进一步利用:
- valid proofs应总是被接受。
- 所支持的所有programs/circuits应被正确处理。
4. 审计ZKP项目的主要挑战及策略
由于近些年才有实用zkSNARKs,审计者审计ZKP项目的主要挑战在于:
- 1)审计ZKP项目的经验有限
- 2)对理论和实现技巧的了解有限
- 3)bug和bug类别的“checklist”有限
- 4)工具和方法有限
大多数bug是由内部或类似项目的团队发现。
为此,对于zkSNARKs这种新密码学应用,要采用新方法来审计:
- 1)与开发者和设计者紧密合作(如联合review、Q&A等)。
- 2)更多威胁分析,以了解应用程序的独特/新风险。
- 3)更多实践经验:写PoC、circuit、proof system等。
- 4)学习之前的失败案例,来源不限于:
- public disclosures and exploits
- 其他审计报告
- 跟踪issue和PR
- 社区
5. ZKP总体流程及失败案例
与第3)节的zkSNARKs安全定义呼应,破坏zkSNARKs安全主要体现在:
- 1)破坏soundness,如利用:
- Contraint system无法有效地强化特定constraints。
- proving keys未安全生成 或 未安全保护。
- 2)破坏zero-knowledge,如利用:
- 将私有数据当成了公开变量。
- 协议层面的"metadata attack"。
- 3)破坏completeness,如利用:
- 边缘情况下R1CS合成行为不正确(例如,关于私有变量数)
- gadget i/o值与类型不匹配引起的gadget组合失败
- 4)破坏(链下)软件,通过任意bug导致:
- 数据泄露,包括通过side channels、encodings(“ZK execution”)。
- 任何形式的不安全状态(code execution, DoS)。
- 5)通过以下方式,使supply-chain被compromise:【即各依赖环节】
- Truste setup的代码和execution.
- build and release process integrity
- software dependencies
- 6)通过合约bug、逻辑缺陷等破坏(链上)软件(包括verifier)。
将ZKP系统分层表示为:
- 1)下层的故障可能会危及所有上层的安全:
- 2)子组件中的故障可能会危及所有上层的安全:
- 3)Security 101:必须定义、实现并测试输入的有效性:
5.1 Filed arithmetic实现引起的soundness问题
Filed arithmetic实现引起的soundness问题的案例主要有:
- 1)appliedzkp的semaphore项目中,未对nullifier(为a shielded payment的unique ID)进行overflow检查引起的双花问题:
- https://kovan.etherscan.io/tx/0x5e8bf35ad76a086b98698f9d20bd7b6397ccc90aa6f85c1c5debc0262be5458a
- https://kovan.etherscan.io/tx/0x9a47cc8daec9d0a5e9a860ada77730190124f9864a5917dcb8f41773d94cfc1a
- 2)eee-oasis的baseline项目中未对a public input进行overflow检查。
- 3)appliedzkp的semaphore项目中未对a public input进行overflow检查。
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;VerifyingKey memory vk = verifyingKey();require(input.length + 1 == vk.IC.length, "verifier-bad-input");// Compute the linear combination vk_xPairing.G1Point memory vk_x = Pairing.G1Point(0, 0);for (uint256 i = 0; i < input.length; i++) {// 注意此处!做overflow检查。require(input[i] < snark_scalar_field, "verifier-gte-snark-scalar-field");vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));}
5.2 R1CS引起的soundness问题
arkworks-rs的r1cs-std项目中的constraint system未对Field element inversion属性进行强化,从而引发soundness问题。
/// Returns `(self / d)`./// The constraint system will be unsatisfiable when `d = 0`.fn mul_by_inverse(&self, d: &Self) -> Result<Self, SynthesisError> {// Enforce that `d` is not zero.d.enforce_not_equal(&Self::zero())?;self.mul_by_inverse_unchecked(d)}/// Returns `(self / d)`.////// The precondition for this method is that `d != 0`. If `d == 0`, this/// method offers no guarantees about the soundness of the resulting/// constraint system. For example, if `self == d == 0`, the current/// implementation allows the constraint system to be trivially satisfiable.fn mul_by_inverse_unchecked(&self, d: &Self) -> Result<Self, SynthesisError> {let cs = self.cs().or(d.cs());match cs {// If we're in the constant case, we just allocate a new constant having value equalling// `self * d.inverse()`.ConstraintSystemRef::None => Self::new_constant(cs,self.value()? * d.value()?.inverse().expect("division by zero"),),// If not, we allocate `result` as a new witness having value `self * d.inverse()`,// and check that `result * d = self`._ => {let result = Self::new_witness(ark_relations::ns!(cs, "self * d_inv"), || {Ok(self.value()? * &d.value()?.inverse().unwrap_or(F::zero()))})?;result.mul_equals(d, self)?;Ok(result)},}}
5.3 hash validation引起的soundness问题
详细参看2019年博客 Tornado.cash got hacked. By us.。
iden3的circomlib中实现MIMC哈希函数的编码错误,Tornado使用circomlib库来构建deposit merkle tree,该编码错误使得可伪造witness的Merkle root并伪造证明。
5.4 论文理论错误引起的soundness问题
BCTV14-Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture 论文中setup描述中的理论缺陷(未清除敏感数据)引起的soundness问题,详细见ZCash 2019年博客Zcash Counterfeiting Vulnerability Successfully Remediated。
5.5 应用中未正确设置nonce值引起的zero-knowledge问题
Aztec中,因未正确设置nonce值引起的zero-knowledge问题,从而破坏了隐私性。详细见博客 Aztec 2.0 Pre-Launch Notes。
5.6 应用中(shielded)交易之间的关联性引起的zero-knowledge问题
ZCash中(shielded)交易之间的关联性泄露有利用价值的信息,详细见2020年论文 Attacking Zcash Protocol For Fun And Profit。
5.7 Prover端缺少(randomized)blinding引起的zero-knowledge问题
dusk-network的plonk中,Prover端缺少(randomized)blinding来隐藏私有输入,从而存在潜在的ZK loss。。
5.8 Merkle tree中不完整的tree constraints引起的DoS问题
aztec中的不完整tree constraints,会引起rollup validation的冻结,从而造成DoS问题。
详细见2021年博客Vulnerabilities patched in Aztec 2.0。
5.9 DSL/签名 引起的Dos/Completeness问题
starkware-libs的cairo-lang项目中的有效签名被拒问题,该风险初期认为是可忽略的,详细见:
- Valid signature rejection not that negligible and possibly exploitable #39
5.10 其它类型的bug
- 1)密码学问题,如:
- Pedersen bases generation/uniqueness基于Pedersen的生成和唯一性
- algebraic hashes 和 commitments的padding方案
- 密码学方案的不合规实现(如 Poseidon algebra bugs)
- Insufficient data being “Fiat-Shamir’d" from the transcript:详细可参见博客 Bulletproofs和Plonk等ZKP系统中Fiat-Shamir实现漏洞Frozen Heart。
- 2)组合性问题:嵌套proof systems之间的不安全交互。
- 3)Side channels问题: Non-ct code, RAM leakage, speculative execution leaks(推测性执行泄露)
6. 结论
6.1 不必过于恐慌
对ZKP的安全不必过于恐慌,因为:
- 已有强健的代码和框架,如arkworks和zkcrypto等Rust项目。
- 使用DSL(如Cairo、Leo等)有助于写更安全的代码,以及使用reusable gadgets/chips。
- 实践中相对窄的attack surface。
6.2 为何需要恐慌?
对ZKP的安全需要恐慌的原因在于:
- 只有少部分人理解zkSNARKs,只有更少部分人能发现bug。
- 缺少工具(如testing、fuzzing、verification)
- 使用更多的ZKP意味着质押更多的钱,也就意味着漏洞研究人员更大的责任。
6.3 需要更多的?
我们需要更多的:
- 测试和(smart) fuzzing、formal verification工具
- 现实世界的说明文档(如代码即文档——cargo spec)
- 信息分享,详细可得的文章,如Bulletproofs和Plonk等ZKP系统中Fiat-Shamir实现漏洞Frozen Heart
6.4 从硬件电路集成中借鉴?
参考资料
[1] zkStudyClub: Zero-Knowledge Proofs Security, in Practice [JP Aumasson, Taurus]
[2] Security of ZKP projects: same but different
零知识证明安全实现经验相关推荐
- 零知识证明学习资源汇总
本文将继续会持续进行更新,更新后的版本将在 Github 和知乎上发布,欢迎关注. Github 地址:https://github.com/sec-bit/learning-zkp/blob/mas ...
- 【区块链技术工坊29期实录】小包总:SERO基于零知识证明的隐私保护公链解决方案
1,活动基本信息 1)题目: [区块链技术工坊29期]SERO基于零知识证明的隐私保护公链解决方案 2)议题: 在区块链隐私保护领域,零知识证明被认为是最前沿的解决方案,同时也是最强大的,以太坊创始人 ...
- 用零知识证明解决投票安全
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 背景 我们经常会遇到需要给别人投票的情况,比如有些公司会组织员工给领导做反向打分,但是往往员工都不敢"真心实意 ...
- 当区块链遇到零知识证明
链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 什么是零知识证明 零知识证明的官方定义是能够在不向验证者任何有用的信息的情况下,使验证者相信某个论断是正确的.这个定义有 ...
- 比较零知识证明算法zkSNARK,zkSTARKs,zkBoo,Sonic,BulletProofs
本文分为两部分,第一部分说明零知识能干什么,为什么它这么强大,在区块链中这么火:第二部分比较零知识证明的算法zkSNARK, zkSTARKs, zkBoo, Sonic和BulletProofs的特 ...
- 零知识证明实践教程,第三部分
本文是零知识证明简单实践教程的第三部分, 第一部分见:零知识证明第一部分, 第二部分见:零知识证明第二部分. 下面这个图片是我们在第二部分所使用的merkle树来构造prover的承诺.同时我们也提出 ...
- 零知识证明实践教程,第二部分
本文是零知识证明简单实践教程的第二部分, 第一部分见:零知识证明第一部分 第三部分见:零知识证明第三部分 现在一个问题是,prover(证明者)可能撒谎,比如原本它应该向verifier(验证者)揭露 ...
- 零知识证明实践教程,第一部分
本文和其他博客文章的区别: 现今存在很多讲解零知识证明的文章,但是它们都是只涉及到很浅层的概念理解和直观感受上面,没有深入到零知识证明的细节,导致读者只知道什么是零知识证明,而不清楚怎么构造一个零知识 ...
- 通过零知识证明,成为重要的区块链革新者
银行巨头ING:通过零知识证明,成为重要的区块链革新者 Captain Hiro 2018-05-02 13:28 发布在 区块链 2 1755 银行业巨头ING将证明创业公司并不是唯一可以推进区块链 ...
最新文章
- 最大似然估计学习总结
- Centos7上使用官方YUM源安装Mysql
- LR模型常见问题小议
- 玩大了!别再埋头学Python了,它真的无用!
- Python编程技巧合集
- 华为最新全系列交换机命令手册、配置指南下载
- 派克dselite调试软件安装_派克ETH电动缸的新专利减少了调试和维护时间
- 普通程序员如何向人工智能方向转型?
- Bootstrap3基础 栅格系统 标尺(col-lg/md/sm/xs-1)
- 使用 ExtJS 实现 ASP.NET MVC 2 客户端验证
- VS2015下安装Visual_Assist_x破解版
- linux服务器架设篇 下载_后渗透系列——下载(Windows篇)
- 3.2.CPU中的实模式
- 挂断电话的实现(即类似于电话号码黑名单)
- CMD命令行下如何切换路径
- 一个轻量级的RGB颜色选择器--jscolor
- RN系列文章---RN简介
- WRL 类库项目模板
- oracle++卸载grid,GRID卸载及重新安装
- 深入Java Thread底层源码实现
热门文章
- java方法的通用格式,【学习笔记】使用Java读取、写入Excel全版本(包含xls、xslx格式)通用方法及代码展示(POI)...
- 自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别
- through2.js,xtend.js源码
- php时间戳求时间差,php中计算时间差的几种方法
- CentOS7 安装 TomCat 7
- 【C#基础】输入一个字符,判定它是什么类型的字符(大写字母,小写字母,数字或者其它字符)
- 十款开发者常用的Chrome插件,让chrome成为开发利器!
- 转 Android屏幕适配全攻略(最权威的官方适配指导)
- ​【​观察】云栖大会共话JDM模式 揭秘创新背后的价值和启示
- mysql CAPI与C++的交互