零知识证明中的专业漏洞分析

本文深入分析了零知识证明实现中的两个关键漏洞,包括离散对数证明中的基数为0攻击和加密离散对数证明中的任意密文伪造问题,揭示了密码学实现中数据验证的重要性。

零知识证明中的专业漏洞分析

零知识(ZK)证明是近年来因加密货币应用而广受关注的密码学工具。其核心思想是:掌握秘密信息(如加密密钥)的一方可以在不泄露秘密本身的情况下,证明关于该秘密的某些陈述。目前加密货币领域正将ZK证明用于匿名交易、隐私保护以及通过"roll-up"系统批量处理交易等场景。在更广泛的领域,ZK证明还允许安全研究人员在不透露漏洞细节的情况下证明漏洞利用能力。

然而,密码学实现中极易出现纰漏。本文将揭示两种特殊用途ZK证明代码中的漏洞,攻击者可利用这些漏洞诱使流行软件接受错误证明,包括对群签名无效输入的"验证"。在ThorChain和Binance等使用门限签名的区块链系统中,此类漏洞可能导致攻击者阻止特定交易完成,造成对整条链或特定参与者的拒绝服务攻击。

离散对数证明背景

离散对数知识证明是一种特殊类型的ZK证明。假设Bob向Alice提供RSA模数N=PQ(P和Q是只有Bob知道的大素数),Bob需要向Alice证明他知道满足s≡tˣ mod N的秘密指数x。该协议运行流程如下:

  1. 双方商定安全参数k(通常设为128)
  2. Bob随机采样aᵢ∈ZΦ(N),计算αᵢ=tᵃⁱ mod N并发送给Alice
  3. Alice响应随机比特序列c₁,…,cₖ
  4. Bob计算zᵢ=aᵢ+cᵢx并发送给Alice
  5. Alice验证tᶻⁱ≡αᵢsᶜⁱ mod N是否对所有i成立

代码实现问题

在tss-lib库的验证函数中,存在关键的数据验证缺失:

1
2
3
4
5
func (p *Proof) Verify(h1, h2, N *big.Int) bool {
    // 缺少对h1,h2,p.Alpha,p.T的非零检查
    modN := common.ModInt(N)
    // ...验证逻辑...
}

攻击者可构造特殊证明:

  • 设置所有p.Alpha[i]=0
  • 设置所有p.T[i]>0
  • 设置h2=0

此时验证等式tᶻⁱ≡0 mod N将恒成立,导致验证者错误接受对不可能陈述(如任意s的基数为0的离散对数)的"证明"。

加密离散对数证明漏洞

在门限签名协议中,另一个关键步骤是同时证明:

  1. X = Rˣ(在阶为q的群G中)
  2. 密文c = PaillierEncₙ(x,r)

kryptology库的实现中存在类似问题:

1
2
3
4
5
6
7
func (p PdlProof) vHatConstruct(pv *PdlVerifyParams) (*big.Int, error) {
    // 当v=s=0时,无论c为何值都能通过验证
    pedersenInc, _ := inc(p.s1, p.s, pv.Pk.N)
    cInvToE := new(big.Int).Exp(cInv, p.e, pv.Pk.N2)
    vHat, _ := crypto.Mul(pedersenInc, cInvToE, pv.Pk.N2)
    return vHat, nil
}

攻击者可设置v=s=0,使得验证等式恒成立,从而"证明"任意密文c都是x的有效加密。

修复方案

两个漏洞的修复方法相似:

  1. 验证所有输入值非零
  2. 检查数值在有效范围内
  3. 确保数值满足乘法关系

对于离散对数证明,应验证h1,h2,p.Alpha非零且与N互质;对于加密证明,应检查z,s∈Z*ₙ且s₁,s₂≠0。

安全影响与披露

这些漏洞存在于GG20门限签名方案的实现中,可能导致:

  • 群签名接受无效输入
  • 区块链系统中特定交易被阻止
  • 门限签名协议遭到破坏

我们已向Binance(修复了tss-lib问题)、ThorChain及其分叉项目(Joltify、SwipeChain)以及Keep Networks披露相关问题。Coinbase也已获知kryptology库的问题。

经验教训

密码学实现必须:

  1. 严格验证所有输入参数
  2. 特别注意0和1等边界值
  3. 将数学描述完整转化为程序约束
  4. 对第三方提供的所有值进行完备性检查

这些案例再次证明,即使是最基础的验证缺失也可能导致严重的安全漏洞。zkdocs.com提供的ZK证明系统资源指南正是为预防此类问题而创建。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计