热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

技术解析CircomPairing库核心零知识电路安全漏洞

零知识领域中的安全问题复杂,开发者不仅需要确保电路计算的正确性,还需要确保零知识验证组件不会接受预期以外的输入输出对。
零知识领域中的安全问题复杂,开发者不仅需要确保电路计算的正确性,还需要确保零知识验证组件不会接受预期以外的输入输出对。

原文标题:《Veridise 截获 Circom-Pairing 核心零知识电路安全漏洞》(Circom-Pairing: A Million-Dollar ZK Bug Caught Early

撰文:Veridise

我们将在本文深入剖析 Veridise 在 circom-pairing 库中发现的一个关键安全漏洞。circom-pairing 库是在业界有着广泛用途的 BLS12-381 椭圆曲线在 Circom 语言上的一个实现:零知识(Zero-Knowledge,ZK)证明系统依赖 circom-pairing 库实现对 BLS12-381 椭圆曲线(elliptic curve)上的签名(signature)的验证。在近期对于 Succinct Labs 的零知识协议进行的安全审计中,Veridise 团队截获了数个存在于 circom-pairing 库的问题。由于该库支撑了 Succinct Labs 的跨链桥(bridge)方案设计,这使得其中最严重的漏洞能被攻击者利用从而实现签名伪造。

想了解更多细节? 前排出售瓜子汽水,坐稳扶好!起飞之前先简单看一下 circom-pairing 库的背景。

Circom-Pairing 库:基于配对的密码学算法的零知识实现

适用于零知识证明的编程语言诸如 Circom 可以将程序的计算逻辑编码成约束(constraints),编译器进而将约束编译为两个零知识证明组件:prover 和 verifier。这两个组件可以被用来验证计算逻辑的正确性。其中,基于满足上述约束的输入 - 输出对(input-output pairs),prover 可以用于生成对应的证明(proofs):比如在 circom-pairing 中,prover 可以用来生成给定公钥的 BLS12-381 签名有效性的证明。而 verifier 组件则可以在不运行(且不知晓)目标计算逻辑的情况下,验证一个给定证明的有效性。并且,由于证明生成的时间取决于约束的规模,多数零知识系统还需要优化以减少 verifier 需要验证的约束的数量。说到这儿,你大概会觉得在 Circom 中实现基于配对的密码学算法(cryptographic pairing algorithms)是一项多么艰巨的任务——对,就是这样。

整数位数不足

实现 BLS12-381 配对算法的首个难点就来自曲线命名中的「381」:381 描述了曲线上表示整数对 (x,y) 所需要的位数(bits),但是现今 Circom 体系中证明的验证只支持 254 位表示的整数。为了绕过这个限制,circom-pairing 的作者需要创建一个支持任意位数整数(简称大整数,bigint)的表示和运算的库。其中,每个库函数及其运算都基于用 k 个寄存器表示的 n 位整数。举个例子,下述代码是一个比较函数(模板)BigLessThan 的整数表示的声明部分:

/*

Inputs:

  - BigInts a, b

Output:

  - out = (a

*/

template BigLessThan(n, k){

  signal input a[k];

  signal input b[k];

  signal output out;

...

}

如果 a 表示的大整数小于 b 表示的大整数,则输出信号(output signal)out 必须被设置为 1,否则为 0(译注:由于 BigLessThan 被用于生成约束而不是计算结果,因此其正确的调用方式中用户必须显式指定 out 的取值:0 或者 1)。circom-pairing 确保了 BigLessThan 中的 a 和 b 都能以大整数的方式表示(k 个寄存器表示 n 位整数)并参与运算,从而克服了原先 254 位的限制。

大规模约束

实现 circom-pairing 的另一个难点就是验证 BLS12-381 所需要的百万级别的约束规模——整个零知识系统中如此量级的约束对于开发者的优化提出了巨大的挑战,而 circom-pairing 中的一个设计决策成为了降低约束数量的关键,即:略过核心功能函数(模板)中的数据验证。比如,circom-pairing 中的一些核心电路(circuits)均假设其输入信号使用了正确的大整数表示并且落在特定范围内。因此,使用这些电路的时候,用户需要额外对其输入进行手动约束(数据验证),例如使用前述的 BigLessThan 函数(模板)。然而,接下来我们将挖掘这个设计所带来的更多安全问题。

信号都约束妥当了吗?仔细再查!

深挖漏洞

我们截获的一个关键漏洞是源于一个叫做 CoreVerifyPubkeyG1 的电路。顾名思义,这是一个用来验证公钥签名的关键电路,因此,在进行实际的签名验证之前,开发者必须确保 CoreVerifyPubkeyG1 的所有的输入数据都满足特定的假设(没错!为了优化约束规模,CoreVerifyPubkeyG1 需要用户手动添加输入约束)。这其中最重要的假设就是:所有曲线上的坐标点都被表示为大整数,并且属于由曲线的质数 q 所定义的有限域(finite field)当中,即[0, q-1) 所表示的整数区间。这些约束由下面的代码片段实现(包含了 10 次我们之前介绍的 BigLessThan 的调用):

// Inputs:

//  - pubkey as element of E(Fq)

//  - hash represents two field elements in Fp2, in practice hash = hash_to_field(msg,2).

//  - signature, as element of E2(Fq2)

// Assume signature is not point at infinity

template CoreVerifyPubkeyG1(n, k){

 ...

 var q[50] = get_BLS12_381_prime(n, k);

  

component lt[10];

// check all len k input arrays are correctly formatted bigints

for(var i=0; i<10; i++){

  lt[i] = BigLessThan(n, k);

  for(var idx=0; idx

    lt[i].b[idx] <== q[idx];

}

for(var idx=0; idx

  lt[0].a[idx] <== pubkey[0][idx];

  lt[1].a[idx] <== pubkey[1][idx];

  ... // Initializing parameters for rest of the inputs

}

 ...

}

看起来好像没啥问题,对吧?其实不然!关键问题就在于数组 lt 的所有输出信号都缺少约束。lt 是 BigLessThan 的实例化。如前文所述,BigLessThan 中如果 a 小于 b,则其输出信号必须被手动设置为 1,否则为 0。由于这里的 CoreVerifyPubkeyG1 并没有检查(设置)lt 的输出信号(译注:也就是说,这里的 lt 原本想约束的 pubkey[0]

漏洞修复

其中一个修复该问题的方案也很简单直接——我们只需要加上丢失的对于 lt 输出信号的约束即可。根据前文所述的 BLS12-381 椭圆曲线的性质,lt 的输出信号必须被设置为 1。以下即为我们给出的修复代码片段(该补丁已被合并入 circom-pairing 库官方版本):

template CoreVerifyPubkeyG1(n, k){

 ...

 var q[50] = get_BLS12_381_prime(n, k);

  

component lt[10];

 ... // Loops same as before

var r = 0;

 for(var i=0; i<10; i++){

   r += lt[i].out;

 }

 r === 10;

 ...

}

经验教训

正如去中心化金融(DeFi)的前尘所反复论及的「失之毫厘,谬以千里」的道理一般,零知识领域中的安全问题只会更加复杂难解:开发者不仅需要确保电路计算的正确性,还需要确保零知识验证组件不会接受预期以外的(多数情况下是非法的)输入输出对——这也使得传统的端到端(end-to-end)测试技术在有别于此的零知识系统架构面前显得捉襟见肘。因此,构建新型的程序分析和验证工具,对于辅助开发者应对种种前沿的零知识技术场景,有着举足轻重的作用。Veridise 的程序分析团队和安全专家们也正致力于研发更加尖端的分析和漏洞捕获工具。今后每月我们会陆续剖析 Veridise 在零知识电路审计过程发现的重大安全漏洞以及我们零知识安全工具的进展, 请关注 Veridise 的技术博客频道的更新。

致谢:我们要感谢 circom-pairing 的作者 Jonathan Wang、Vincent Huang 和 Yi Sun,以及来自 Succinct Labs 的 Uma Roy 和 John Guibas——感谢他们与 Veridise 团队在整个审计过程中的高效合作以及为本文写作提出的建设性的意见。


推荐阅读
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
author-avatar
xwu9052591
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有