返回论坛

Poseidon 哈希延展性漏洞分析:Iden3 库实现中的安全隐患

查找币 漏洞披露 安全研究 Web3安全 区块链安全

查找币安全研究院

钱包恢复评估 | 链上取证分析 | Web3 事件响应
以合法授权、证据保全、隐私保护和可复核流程为前提,不要求用户在线提交完整私钥或助记词。

查看研究院 研究报告中心
## 背景 在零知识证明(ZK)技术日益普及的今天,哈希函数的安全性成为区块链应用的核心关注点之一。此前,我们在《哈希函数的隐藏危险:长度扩展攻击与服务端验证的安全隐患》一文中,已经详细探讨了 MD5、SHA1、SHA2 等传统哈希算法存在的延展性问题及其潜在风险。 近日,安全研究员在 X 平台披露了 Iden3 密码学库中存在的 Poseidon 哈希延展性问题。查找币安全团队对此进行了深入分析,并在此分享技术细节与防护建议。 ## Poseidon 哈希函数概述 Poseidon 是一种专为零知识证明系统优化的密码学哈希函数,具有以下核心特性: - **有限域运算**:在素数域上运行,特别适合基于算术电路的 ZK 系统 - **高效性**:计算效率高,Gas 消耗低,适合链上使用 - **主要用途**:Merkle 树构建、数据承诺方案等 - **广泛应用**:被 zkRollup、身份验证、Circom 等主流 ZK 项目采用 Poseidon 的设计使其在 ZK 生态中占据重要地位,但实现中的细节偏差可能引入严重安全风险。 ## 标准 Poseidon 的防延展性设计 标准 Poseidon 算法基于海绵结构(Sponge Construction),其填充机制天然具备抗延展性: 1. 在消息末尾添加一个“1”元素 2. 补充足够数量的“0”元素 3. 确保消息长度是 `(t - c)` 的整数倍(t 为状态宽度,c 为容量) 这种设计的核心优势在于:**攻击者无法从最终哈希值恢复内部状态**,因此无法进行长度扩展攻击。 对比具有延展性的传统哈希(如 SHA256): | 特性 | SHA256 | Poseidon(标准) | |------|--------|------------------| | 填充方式 | 追加长度信息 | 固定长度填充 | | 状态恢复 | 可从哈希值恢复 | 不可恢复 | | 延展性风险 | 存在 | 不存在 | ## Iden3 实现中的延展性问题 问题出现在 Iden3 库的具体实现中。其 `HashBytes` 函数采用了与标准不同的填充方案: ```go func HashBytes(msg []byte) (*big.Int, error) { inputs := make([]*big.Int, spongeInputs) for j := 0; j < spongeInputs; j++ { inputs[j] = new(big.Int) } dirty := false var hash *big.Int var err error k := 0 for i := 0; i < len(msg)/spongeChunkSize; i++ { dirty = true inputs[k].SetBytes(msg[spongeChunkSize*i : spongeChunkSize*(i+1)]) if k == spongeInputs-1 { hash, err = Hash(inputs) dirty = false if err != nil { return nil, err } inputs = make([]*big.Int, spongeInputs) inputs[0] = hash for j := 1; j < spongeInputs; j++ { inputs[j] = new(big.Int) } k = 1 } else { k++ } } if len(msg)%spongeChunkSize != 0 { var buf [spongeChunkSize]byte copy(buf[:], msg[(len(msg)/spongeChunkSize)*spongeChunkSize:]) inputs[k] = new(big.Int).SetBytes(buf[:]) dirty = true } if dirty { hash, err = Hash(inputs) // ... } } ``` ### 核心问题分析 1. **纯零填充(Zero Padding)**:对于长度不足 31 字节的末块,直接补零至满块 2. **缺少分隔符**:未在消息末尾添加标准规定的“1”分隔符 3. **状态混淆**:攻击者可通过构造特定输入,使不同消息产生相同哈希值 ## 攻击场景与影响 ### 攻击原理 假设存在两个不同消息 `M1` 和 `M2`,其中 `M2 = M1 || 0x00`(在 M1 后追加零字节)。由于 Iden3 实现的填充机制,两者可能产生相同哈希值: - `M1 = "deadbeef"` → 填充为 `deadbeef0000...`(31 字节) - `M2 = "deadbeef00"` → 填充为 `deadbeef0000...`(31 字节) 攻击者可以利用这种碰撞破坏系统的安全验证机制。 ### 受影响的应用 - **zkRollup**:交易数据的 Merkle 树验证 - **身份验证系统**:零知识证明中的身份承诺 - **Circom 智能合约**:使用 Poseidon 哈希的电路验证 - **跨链桥**:依赖哈希一致性的跨链消息验证 ## 防护建议 针对此漏洞,查找币安全团队建议: 1. **立即升级库版本**:检查使用的 Iden3 库是否为受影响版本,及时更新 2. **验证填充逻辑**:确保实现遵循 Poseidon 标准规范(EPRINT 2019/458) 3. **使用封装函数**:优先使用官方推荐的哈希接口,避免直接调用底层函数 4. **审计依赖链**:检查所有依赖该库的项目,确保无间接影响 5. **增加输入验证**:对哈希输入进行归一化处理,避免长度歧义 ## 总结 Poseidon 作为 ZK 生态中的核心哈希函数,其安全性至关重要。Iden3 库的实现偏差虽然看似微小,但足以引发哈希碰撞攻击,威胁依赖该库的众多区块链应用。这一案例再次提醒我们:**密码学实现的任何细节偏差,都可能成为攻击者利用的突破口**。 开发团队在采用密码学库时,应始终关注实现的标准化程度,并定期进行安全审计。查找币安全团队将持续关注此类漏洞,为区块链生态安全提供专业支持。 --- *本文由查找币安全团队整理发布*
在论坛中查看和回复