速率限制清除器 (RLN) 协议 - Circom 电路安全审核

  • thogiti
  • 发布于 2023-10-19 19:56
  • 阅读 51

本文是关于Rate Limiting Nullifier(RLN)零知识证明协议的安全审核报告,详细介绍了审核期间发现的问题和建议,以及RLN的应用场景和相关原理。审核发现了低影响的漏洞,并提供了详细的修复建议。总体而言,代码实现了良好的数学操作和基本功能,但在文档和测试验证方面仍可提高。

速率限制无效化器 (RLN) 审查

我最近有幸对一个 Zero Knowledge Proofs (ZKP) 协议进行首次安全审计。此协议是速率限制无效化器 (RLN) Zero Knowledge Proofs 协议,其电路使用 Circom 编写。我的审查主要集中在 Zero Knowledge Proofs 小工具的 Circom 电路上。让我告诉你,这真是一场冒险!我是说,谁知道数学可以如此令人兴奋?

在审查 RLN Zero Knowledge Proofs 协议期间,我学到了很多关于 RLN 规范、验证和如何识别约束不足系统的复杂知识。我的数学背景在帮助我理解这些复杂概念时证明是无价的。人们总是说,“数学是宇宙的语言”!但说真的,这些东西是谁想出来的?此外,我对 ZKP 原语攻击向量和系统中其他潜在脆弱性的理解也更深刻了。这就像一个侦探,但面对的是 ZKP 系统!来告诉你,这并不像看起来那么简单。

审查资源:

审计员:

目录 <!-- omit in toc -->

执行摘要

范围

发现解释

关键发现

高影响发现

中等影响发现

低影响发现

最终意见

执行摘要

  • 代码中没有关键或高影响的错误。
  • 发现了一些低影响错误,主要是 Circom 电路与其相应的 Solidity 合同之间输入变量的约束不足。

速率限制无效化器

速率限制无效化器 (RLN) 是一个基于零知识证明的构造(有时称为 ZKP 小工具),它提供了一种适用于去中心化(和中心化)环境的匿名速率限制信号/消息框架,使用的是秘密沙密尔共享 (SSS) 方案。

动机 在匿名去中心化网络中,速率限制无效化器的一些应用包括:

  1. 去中心化投票应用:RLN 有助于防止投票结果受到垃圾邮件或 Sybil 攻击的操纵,确保投票过程的完整性。
  2. 匿名群聊应用:通过防止用户进行垃圾信息轰炸或污染群聊,RLN 提升了这些应用中的用户体验。
  3. 直接匿名证明:RLN 可与直接匿名证明 (DAA) 配合使用,实现服务速率限制,在用户与服务之间的消息匿名发送的同时,保持消息不可链接性。
  4. 基于区块链的社交网络:RLN 可应用于去中心化社交媒体网络,以防止向 API 和应用程序发送垃圾邮件、Sybil 攻击和其他类型的滥用,从而增强这些网络的整体安全性和可靠性。
  5. 网页应用的速率限制:RLN 可与网络应用防火墙 (WAF) 集成,以保护免受拒绝服务攻击、暴力破解登录尝试和 API 流量激增的影响,从而提供更安全、更可靠的网页应用体验。

RLN V2 RLN V2 协议是一个更为通用的构造,允许为一个 Epoch 设置不同的限制(在 RLN-V1 中是每个 Epoch 1 条消息),同时仍保持与其前身一样简单。此外,它还允许根据某些公共数据(例如股份)为不同的 RLN 应用用户设置不同的速率限制。

RLN Circom 电路的审查持续了 13 天。从 2023 年 5 月 31 日到 6 月 12 日进行了代码审查。在审查期间,RLN 仓库在积极开发中,但审查限制在最新提交 37073131b9 开始时。

RLN 电路的官方文档位于 rate-limiting-nullifier.github.io

流程

这是 RLN 协议的完整流程图,用于 Circom 电路。

RLN Protocol Flow


    graph TD
        ext_null>外部无效化器] --> h1(哈希)
        secret{{秘密密码与无效化器}} --> h0(哈希) --> a_0
        a_0{{秘密哈希 a_0}} --> h1
        msg_id>消息_ID `k`] --> h1
        msg_id --> limit_check(消息限制检查)
        msg_limit>消息限制] --> limit_check
        h1 --> a_1 --> h2(哈希) --> int_null([内部无效化器])
        a_1 --> times
        m>消息] --> h3(哈希) --> times(*) --> plus(+)
        a_0 --> plus --> sss([沙密尔的分享 y_share])
        a_0 --> h4(哈希) --> id_com([id_承诺])
        h4 --> merkle(Merkle证明)

范围

审查的范围包括指定提交中的以下电路:

在发现结果呈现给 RLN 团队之后,进行了一些修复并包含在几个 PR 中。

此审查是代码审查,以识别代码中的潜在漏洞。审查员未调查安全实践或操作安全,并假定可以信任特权帐户。审查员没有根据某个标准或规范评估代码的安全性。审查可能没有发现所有潜在的攻击向量或漏洞领域。

yAcademy 和审计员对代码的安全性不做任何保证,并且不保证代码没有缺陷。yAcademy 和审计员不向第三方表示或暗示代码已被审计或代码没有缺陷。通过部署或使用代码,RLN 和合同的用户同意自担风险使用该代码。

代码评估矩阵

分类 评分 描述
访问控制 不适用 代码没有明确实现访问控制机制。它没有针对谁可以访问或修改数据的具体检查或限制。
数学 良好 代码包括数学运算,如加法、乘法和使用 Poseidon 函数的哈希。它还包括范围检查和位操作。
复杂性 良好 代码的复杂性相对较低。它由基本数学运算组成,并包括Merkle树的包含证明和范围检查。
一般 代码包括 Circomlib 库,特别是用于哈希的 Poseidon 电路。
去中心化 不适用 代码没有明确处理去中心化。它没有包括用于分布式共识或与去中心化网络交互的机制。
代码稳定性 良好 代码似乎结构良好,并遵循 Circom 语法。它没有包含任何明显的错误或影响其稳定性的问题。
文档 代码没有包括广泛的文档。有些评论解释了某些组件的目的,但更详细的文档将是有益的。
监控 一般 代码没有包括具体的监控机制。它没有内置的日志记录或事件或性能指标的跟踪。
测试与验证 一般 代码包括一些基本的范围检查和Merkle树的包含证明,这些对于确保代码的正确性很重要。然而,它没有包括全面的测试或验证程序。

发现解释

发现分为以下几个部分,按其影响分类:

  • 关键、高、中、低影响
    • 这些发现范围从可能导致资金损失的攻击、影响合约的控制/所有权,或导致任何超出需求范围的意外后果/行为
  • Gas节约
    • 能够提高合约Gas效率的发现
  • 信息性
    • 包括推荐和最佳实践的发现

关键发现

1. 关键 - 对于某些输入 x(消息的哈希),identitySecret 被泄露

当输入信号 x(消息的哈希)为 0 模素数 p(标量场使用的)时,identitySecret 被泄露。当 x021888242871839275222246405745257275088548364400416034343698204186575808495617(以太坊)或素数 p 时,标量场的 $Fp$ 算术电路的乘积 a1 * x 变为零,从而泄露了 identitySecret

  • 这个素数 p 是 $BN254$ 曲线的标量场的阶。
  • Circom 2.0.6 引入了两个新的素数以供使用
    • $BLS12-381$ 的标量场的阶。
    • 52435875175126190479447740508185965837690552500527637822603658699938581184513
    • 金丝雀素数 18446744069414584321,最初用在 $Plonky2$ 中。

推荐解决方案

对输入信号 x 和乘积 a1 * x 施加约束,确保二者都在模素数 p 下非零。

isZero(x).out === 0
isZero(a1*x).out === 0

高影响发现

无。

中等影响发现

无。

低影响发现

1. 低 - RLN 合同与 RLN 电路之间用户邮件限制位数不一致

在 RLN.sol 中,messageLimit 最多可以取到 2256 - 1 的值,而电路中的 messageId 和 userMessageLimit 的值限制为 216 - 1。

rln.circom

template RLN(DEPTH, LIMIT_BIT_SIZE) {
...
    // messageId 范围检查
    RangeCheck(LIMIT_BIT_SIZE)(messageId, userMessageLimit);
...
}
component main { public [x, externalNullifier] } = RLN(20, 16);

rln.sol

uint256 messageLimit = amount / MINIMAL_DEPOSIT;

推荐解决方案

更新 rln.sol 中的相关代码,如下所示:

function register(uint256 identityCommitment, uint256 amount) external {
        ...
        uint256 messageLimit = amount / MINIMAL_DEPOSIT;
        require( messageLimit &lt;= type(uint16).max , "最大消息限制长度为 65535");
        ...
    }

2. 低 - 在 Withdraw 电路中未使用的 address 输入信号

输入信号 address 被声明但是未在输出计算中使用。

    signal input address;

推荐解决方案 为未使用的输入信号 address 分配一个本地计算。例如:

   signal addressDoubled &lt;== address + address;

3. 低 - 输入数据缺少范围检查

Circom 电路缺少对多个输入参数(如 DEPTHaddressLIMIT_BIT_SIZE 等)的显式范围检查。

推荐解决方案 执行显式范围检查,并约束数据输入参数,以提高 ZKP 系统的可靠性。

信息性发现

Circom 电路进一步使用来自 0xParc 的 Ecne 工具 测试 Weak Verification 可证明性属性。这测试了在 QAP(R1CS 约束)中,给定输入变量时,输出变量是否具有唯一确定的值。一种约束不足的电路允许在给定相同输入的情况下为多个不同的输出生成有效证明。最糟糕的情况下,攻击者可以针对任何输出生成约束不足电路的有效证明——这意味着攻击者能够说服一个验证者(错误地)相信该电路是适当约束的,从而攻击者知道任意输出的原像。

Ecne 发现

Circom 电路编译为非优化的 R1CS 约束系统,然后进行了 Weak Verification 测试,以检查是否存在不良的约束或约束不足。所有电路在 Ecne 测试中均通过,没有不良或约束不足的情况。这验证了给定电路的 R1CS 方程在给定输入时唯一确定输出(即,这些约束是有效的)。

错误处理

考虑添加以下错误处理,以检查特定条件,并在不满足这些条件时抛出错误或返回错误代码。这有助于提供有意义的错误消息或以可控的方式处理异常情况。

rln.circom

// 为Merkle树包含证明添加错误处理
root &lt;== MerkleTreeInclusionProof(DEPTH)(rateCommitment, identityPathIndex, pathElements);
assert(root !== 0, "无效的Merkle树包含证明"); // 如果Merkle树包含证明无效,则抛出错误

withdraw.circom

// 为地址长度检查添加错误处理
assert(address.length == EXPECTED_ADDRESS_LENGTH, "无效的地址长度"); // 如果地址长度不符合预期,则抛出错误

utils.circom

// 为长度检查添加错误处理
assert(leaf.length == EXPECTED_LEAF_LENGTH, "无效的叶子长度"); // 如果叶子长度不符合预期,则抛出错误

POSEIDON 和一些附加说明

  • RLN 电路假设基础哈希函数(Poseidon)是:
    • 抗碰撞的
    • 抵御差分、代数和插值攻击
    • 表现得像一个随机预言机
  • 用于成员证明的Merkle树被假定为安全,抵御第二次预成像攻击。
  • 电路的安全性依赖于用于范围检查和 SSS 份额计算的加密原语的安全性。
  • 电路的安全性也依赖于 identitySecret 信号的保密性,假定由用户保管。
  • 社交工程攻击仍然是破坏系统的有效方式。
  • 攻击者可以通过社交工程、钓鱼攻击或利用用户系统的漏洞来获取用户的 identitySecret 信号。
  • 一旦攻击者获取了 identitySecret 信号,他们就可以计算该用户的 identityCommitmentrateCommitmenta1y 信号,并利用这些信息破坏 RLN 电路的安全性。

最终意见

总体而言,代码在数学运算和基本功能的实现上表现良好。然而,它可以受益于更广泛的文档和额外的测试及验证程序。

  • 原文链接: github.com/thogiti/thogi...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
thogiti
thogiti
https://thogiti.github.io/