跳转到主要内容

热门内容

今日:


总体:


最近浏览:


Chinese, Simplified

category

Pedersen承诺

​作者:Oleg Burundukov​
​阅读时间:6分钟​
​发布日期:2023年7月21日​


承诺方案

承诺方案(Commitment Scheme, CS)是密码学协议的基础构件。CS以消息作为输入,为验证者生成“承诺”。随后,当被揭示给时,可通过高效算法验证的唯一对应性。CS的正式定义可见于多部著作(如[1])。承诺方案具备以下关键特性:

  1. ​隐藏性(Hiding)​​:验证者无法从中推测出。即对于不同的消息,承诺的分布是统计不可区分的。
  2. ​绑定性(Binding)​​:承诺者无法通过修改生成相同的

Pedersen承诺

Pedersen承诺由T.P. Pedersen在[2]中提出。该方案构建于素数阶子群中,选取生成元,并令,其中同属一个子群。承诺者通过计算对消息进行绑定,其中中随机采样。后续需通过揭示对来验证承诺。显然,已知时,验证算法是高效的。文献[2]严格证明了该承诺方案的完美隐藏性。此外,由于随机数的存在,同一可生成多个不同的承诺,而无需暴露本身。

​绑定性如何?​​ 承诺者通过群中的双指数乘积进行绑定,其中属于同一群的不同元素。Pedersen在论文中指出,无人知晓。假设相反:承诺者已知中的,则她可通过调整任意修改,同时保持承诺不变。若承诺者能通过第三方提供的计算离散对数,则绑定性将被破坏,但此类计算需要无限资源,实际不可行。因此,只要承诺者不知晓,该方案即具备绑定性。根据文献,需由可信方为承诺者提供(但非)。

类似方案还有ElGamal承诺,其不仅共享上述机制,还额外公开。由于不匹配时承诺者无法修改,该方案具备完美绑定性——即使计算能力无限的承诺者也无法作弊。


Pedersen承诺在区块链中的应用

Pedersen承诺已成为复杂密码学协议(尤其是多方计算)的重要工具。在多场景中,参与方需预先承诺其后续分享的值,以防止其他方根据输入动态伪造值。该方案也可用于交互式零知识证明协议(ZKP),承诺者通过随机性对秘密输入进行承诺(但无需揭示),并依赖Pedersen承诺的计算绑定性确保协议可靠性。

在ZKP用于MPC门限签名的典型案例[3]中,Pedersen承诺被用于关键的ZK范围证明。值得注意的是,[3]中的Pedersen承诺基于RSA群(两个素数的乘法模群),而非素数阶群,因此作者称其为“环式Pedersen承诺”。此调整不影响绑定性——承诺者仍通过强RSA假设被绑定至,除非其知晓相对于的离散对数。

​若承诺者使用已知关系的Pedersen参数会怎样?​​ 她可伪造协议,即使输入本应失败,验证仍会通过。例如,在[3]的“无小因子证明”协议中,前两步验证本质为利用Pedersen加法同态性的Schnorr证明。若恶意承诺者已知的关系,则可篡改后续输出以满足验证条件(详见[4])。


多方协议中的参数生成漏洞

在分析多个开源实现时,我们发现​​参数生成权的归属问题​​是导致安全漏洞的核心。以下通过代码实例解析具体问题:

1. 本地化参数生成(关键代码段)

go

复制

// 证明N为Blum素数(图1)
mod := zkmod.NewProof(h.Clone(), zkmod.Private{
    P:   r.PailierSecret.P(),
    Q:   r.PailierSecret.Q(),
    Phi: r.PailierSecret.Phi(),
}, zkmod.Public{N: r.NModulus[r.SelfID()]}, r.Pool)

// 生成Pedersen辅助参数(问题点)
fac := zkfac.NewProof(zkfac.Private{
    P: r.PailierSecret.P(),
    Q: r.PailierSecret.Q()}, 
    zkfac.Public{
        Aux: pedersen.New(
            arith.HandlerFunc(s(r.PailierSecret.Q())),
            r.S[r.SelfID()],  // ⚠️ 本地生成S参数
            r.T[r.SelfID()],  // ⚠️ 本地生成T参数
            ...
        ),
    }, r.Pool)

​问题分析​​:

  • r.S[r.SelfID()]r.T[r.SelfID()]从本地存储获取参数,而非可信第三方
  • 违反协议[3]中"Prover必须使用由Verifier提供的(g,h)"的安全假设
  • 允许恶意Prover构造特殊参数绕过后续验证

2. 违规广播机制(图2代码)

go

复制

func (r *round2) Finalize(out chan<- *round.Message) (round.Session, error) {
    // 广播包含本地参数的承诺(问题点)
    err := r.BroadcastMessage(out, &broadcast3{
        RID:   r.RIDs[r.SelfID()],
        C:     r.ChainKeys[r.SelfID()],
        S:     r.S[r.SelfID()],  // ⚠️ 广播本地S
        T:     r.T[r.SelfID()],  // ⚠️ 广播本地T
        ...
    })
    if err != nil {
        return r, err
    }

​问题分析​​:

  • 所有参与方强制使用Prover生成的S/T参数
  • 破坏多方协议中「每个Verifier独立验证」的核心机制
  • 攻击者可构造恶意参数组实施协同攻击

漏洞影响与修复方案

​潜在攻击场景​​:

  1. ​参数伪造攻击​
    恶意节点生成S = g^a, T = h^b,其中a,b为已知值。在后续证明阶段,可通过调整随机数r伪造多个承诺的绑定关系。

  2. ​参数复用攻击​
    复用同一组(S,T)参数生成不同承诺,利用参数间的数学关联性破解隐藏性。

​修复建议​​:

go

复制

// 修复方案伪代码
type TrustedSetup struct {
    S, T *big.Int // 由可信第三方生成
}

func ValidProof(trusted TrustedSetup) {
    // 强制使用外部参数
    aux := pedersen.New(trusted.S, trusted.T) 
    proof.Generate(..., aux)
}

// 多方协议中每个节点独立验证
func Verify(proof Proof, trusted TrustedSetup) bool {
    return proof.CheckConsistency(trusted.S, trusted.T)
}

​实施要点​​:

  • 参数生成权收归可信初始化阶段
  • 每个参与方维护独立的参数验证上下文
  • 增加参数来源的完整性校验(如数字签名)

执行摘要

当前,多方计算及相关协议已成为区块链交易签名中保障安全与隐私的核心工具。门限签名算法需确保加密钱包不被攻击,其设计依赖专业密码学家的数学理论(通常以学术论文形式呈现)。然而,实现者可能因对形式化语言的理解偏差引入错误,涉及ZKP、承诺方案等关键模块。

为此,我们强调以下重要性:

  • 仔细审查学术协议中未显式声明的密码学假设
  • 开源关键密码学代码
  • 在软件开发中实施“四眼原则”(多人审查)
  • 定期进行外部安全评估

免责声明

本文经与代码所属公司Taurus SA协调并完成负责任的披露后发布,休眠期为4周。


参考文献

[1] 《现代密码学导论》,Katz与Lindell,第三版,第6.6.5节
[2] 《非交互且信息论安全的可验证秘密共享》,Torben Pryds Pedersen
[3] 《UC非交互、主动式、可识别中止的门限ECDSA》,Canetti等,2021
[4] 《开源项目中Pedersen承诺的使用注意事项》,METACO Labs,2023

https://www.metaco.com/wp-content/uploads/2023/07/no_small_factor_zkrp…
[5] Safeheron C++门限ECDSA实现,2023

https://github.com/Safeheron/multi-party-ecdsa-cpp
[6] Taurus多方签名协议实现,GitHub

https://github.com/taurusgroup/multi-party-sig

本文地址
最后修改
星期一, 四月 28, 2025 - 12:33
Article