# 秘诺切换简介 *阅读其它语言版本: [English](../switch_commitment.md)* ## 概述 密码学中,_秘诺_ (或_秘诺方案_)这个概念可以想像成一个加锁的盒子。可以在盒子里放东西(例如一张写着密码的纸),把盒子锁起来,再交给另一个人(或公示)。 另一个方不知道盒子里的密码,但是如果你决定之后按约定公开密码,并要证明这确实是最初你放在盒子里的密码(并未篡改),你仅把盒子钥匙交给另一个人即可证明。 另一个人可以打开盒子,对比盒子里的密码和你刚刚公开的密码,就可以确定盒子上锁后密码没有变更。你提前"**承诺**"密码,意味着在秘诺生成和公开之间,你不可以对其做任何修改。 ## 范例 ### 秘诺哈希计算 使用密码学哈希函数即可实现简单的秘诺方案 (commitment scheme)。例如,Alice 和 Bob 想要玩“猜数游戏”。Alice 想出自己的密数 `29`,由 Bob 来猜。在游戏开始前,Alice 做如下计算: hash( 29 + r ) 并把结果告诉给 Bob。`r` 是随机选择的_“致盲因子 (Blinding Factor)”_。之所以需要致盲因子是因为如果没有,Bob 就可以尝试所有可能数字的哈希值,来对比原哈希值。 游戏结束时,Alice 仅需公开自己的密数 `29` 和盲因子 `r`。Bob 自己哈希计算结果,即可验证 Alice 在游戏过程中是否更改过密数。 ### Pedersen Commitment 另外,高阶秘诺方案还有其他特性。例如 Mimblewimble 和机密交易 (Confidential Transactions,CT) 大量使用_同态 (homomorphic)_ 秘诺的 _[Pedersen Commitments](https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf)_。这里的“同态”是指,引用上述“盒子”的比喻,可以使用两个加锁盒子(_盒子 1_ 和_盒子 2_),而且可以将其_“合并”_一起。这样你就得到一个大盒子(仍旧加锁),如果之后打开这个含有密数的大盒子(如上述范例),最终的结果就是_盒子 1_ 和_盒子 2_ 的密数总和。 这个“盒子”的比喻在现实世界中看似不合理,但对椭圆曲线原理无可挑剔。 如需了解关于 Pedersen Commitment 的详情,请参阅[《Mimblewimble 和 Grin 简介》](intro_ZH-CN.md) ## 秘诺方案特性: 一般而言,秘诺有两大特性,强弱变化视秘诺方案类型而变。 - **隐匿性(或机密性):**秘诺方案保护秘诺的强度。或依上述范例:攻击者没有钥匙怎么能打开盒子(知道密数)? - **绑定性:**攻击者是否可以找到匹配同一秘诺的不同密数,攻击者之后通过秘诺打开的就是不同秘诺。这样秘诺的_致盲性_就被破解。 ### 两种特性的安全性: 对于这两种特性,可以确认不同安全级别。 两种特性最重要的混合使用方式为 - **完美绑定**和**计算隐匿**秘诺方案,和 - **计算绑定**和**完美隐匿** “_计算_”绑定或隐匿的基础数学难度很高,以现有计算能力在合理时间内难以破解(即以世界上的现有计算资源今天不可破解),因此意味着这种特性(绑定性/隐匿性)安全。 “_完美_”绑定或隐匿意味着即使有无限计算资源,也不可能破解这一特性(绑定性/隐匿性) ### 互不相容: 需要意识到重要的一点,秘诺方案**不可能**同时兼备_完美绑定_**和**_完美隐匿_。一个思想实验就可以明白:假设攻击者有无限算力,他可以对任意数值生成秘诺(和致盲因子),直到碰撞找到匹配原始秘诺的输出数值。进一步假设秘诺方案为_完美绑定_(意味着不可能两个不同的数值生成相同秘诺),匹配秘诺的数值独一无二,那这样就会破坏隐匿性。 反之亦然。如果一个秘诺方案为_完美隐匿_,那必然会有多个输入值生成相同秘诺(否则有无限算力的攻击者只需如上所示计算任意数值)。结果就是,这一秘诺方案不可能是_完美绑定_。 #### 有所取舍 此处的要点就是:**总要有所取舍**,无法兼备两种特性(_隐匿性_和_绑定性_)的_完美_安全性。如果一种是_完美_安全,那另一种至多就是_计算_安全(反之亦然)。 ### 加密货币中的应用考虑 在设计加密货币时,这些特性扮演了哪些作用? **隐匿性**: 对于 Grin 这类注重隐私的加密货币,秘诺方案用以保护交易数据。发送者执行发送一定数量的币,但对于他人具体金额保密(秘诺方案中的_隐匿性_特性)。 **绑定性**: 同时,交易发起者之后也无法更改秘诺为不同的交易金额。如果更改秘诺成功,攻击者就可以花费比之前在一个 UTXO 生成的币多的金额,这样就凭空造出“假币”。更糟的是,由于金额隐藏,这种情况有可能无法被发现。 所以保持两种特性安全可靠是根本所在。 只要一个加密货币始终维持这两种特性,就得选择使用哪种秘诺方案。 #### 难以选择? 哪种特性需要_完美_安全,哪种足以_计算性_安全?换句话说:如果秘诺方案被意外攻破,应该提高哪种特性安全级别?是经济稳定性(无通胀可能)还是保证隐私性(隐私不被侵犯)? 这似乎是个难题。 深入了解,我们意识到秘诺方案被攻破时需要_完美_绑定。那时候即使只有_计算_绑定也会安全。 同时隐私加密货币需要**永远**保证_隐匿性_。_绑定_特性只有在创建交易且不会影响过去交易的情况下才重要。不同的是,需要始终保持_隐匿性_。否则遇到意外秘诺方案被攻破的情况下,攻击者会链上回滚,解绑历史交易,进而破坏隐私性。 ## Pedersen Commitments 特性 Pedersen Commitments 是**计算绑定**和**完美隐匿**。预设秘诺值为 `v`: `v*H + r*G`,会存在一组不同的值 `r1` 和 `v1` 其和与预设秘诺值相同。即使有无限算力可以尝试所有可能的值,攻击者也无法分辨哪一个是原始秘诺(因而是_完美隐匿_)。 ## 秘诺切换简介 如果 Pedersen Commitment 的绑定性被意外破解那会发生什么? 一般而言,加密货币的秘诺方案被破解,就会更改加密方案。但问题是更改加密方案就需要使用新的方案创建新的交易输出,来保证资金安全。这就需要每位持币者将币转到新的交易输出。如果没有转币到新交易输出,那就不会受到新秘诺方案的保护。而且一定要在就方案被大规模攻破**之前**转币,否则现有 UTXO 不会记录正确的交易值。 遇到这种情况,[_Switch Commitments_](https://eprint.iacr.org/2017/237.pdf) 给出了简洁的解决方案。这种秘诺仅靠更改公开/验证程序来变更秘诺特性,而无须变更秘诺创建方式。(“_切换_”到新验证方案,可与在“_切换_”倩生成的秘诺兼容。) ### 工作方案 首先来介绍新的秘诺方案:**ElGamal commitment** 方案。其为_完美绑定_(由于不能二者兼具所以是_计算隐匿_)。其特征与 Pedersen Commitments 极其类似,只是添加了新元素,致盲因子 `r` 与 `J` 相乘计算得出: v*H + r*G , r*J 如果我们储存额外的域 `r*J`,并且暂时忽略,我们可以将其视作 Pedersen Commitments 对待,未来随时可以激活完整 ElGamal commitment。主网上线前,[Grin 早期版本](https://github.com/mimblewimble/grin/blob/5a47a1710112153fb38e4406251c9874c366f1c0/core/src/core/transaction.rs#L812)就是这样部署。详情为:哈希值 `r*J` (_switch\_commit\_hash_) 添加到交易输出,但造成每个输出大小增加 32 字节。 幸运的是,之后 Mimblewimble 邮件列表成员 Tim Ruffing 提出一个[绝妙的解决方案](https://lists.launchpad.net/mimblewimble/msg00479.html)(最初是 Pieter Wuille 所建议)。这一方案保持了相同优势,但不会对交易输出造成额外体积负担。 方案内容如下: 普通的 Pedersen Commitment 是这样: v*H + r*G (`v` 是输入/输出值,`r` 是随机致盲因子,`H` 和 `G` 是椭圆曲线上的两个生成点)。 如果加以更改,让 `r` 变为非随机数,但使用另一个随机数 `r`,来创建 Pedersen Commitment: v*H + r*G 例如: r = r' + hash( v*H + r'*G , r'*J ) (使用椭圆曲线上的另外第三生成点 `J`),然后 `r` 因为仍旧随机分布,所以作为致盲因子仍完美有效,但我们现在看到的括号内哈希函数 (`v*H + r'*G , r'*J`) 是 **ElGamal commitment**。 这一绝妙的方案就从输出中移除了秘诺切换哈希(详情请参阅 [pull requests](https://github.com/mimblewimble/grin/issues/998)),这样就可以轻松纳入 Pedersen Commitment。 这就是 Grin 目前的秘诺部署方案。Pedersen Commitment 用作机密交易 (Confidential Transaction),但没有单纯随机选择致盲因子 `r`,而是在一个随机数 `r` 添加 ElGamal commitment 函数来计算(详情请参阅 [main_impl.h#L267](https://github.com/mimblewimble/secp256k1-zkp/blob/73617d0fcc4f51896cce4f9a1a6977a6958297f8/src/modules/commitment/main_impl.h#L267))。 总之,秘诺切换是在论文[《秘诺切换:安全切换机密交易》](https://eprint.iacr.org/2017/237.pdf)中首次提出。“切换”一词来源于未来可以随意“扳动开关”这一想法。仅仅变更验证程序就可以更改秘诺绑定性和隐匿性特性强弱,未来的更改甚至可与创建的历史秘诺兼容。 ## 结语 Grin 和其他加密货币一样,都使用 Pedersen Commitments。唯一的区别就是随机致盲因子 `r` 是利用 ElGamal commitment 方案生成。 这种方案看上去没有差别,但有重要的安全措施: Pedersen Commitments 已经是_完美绑定_。所以无论发生什么,无需用户任何操作就可保证无隐私泄露风险。若遇到意外,秘诺方案的绑定性被破解,需要所有新交易通过验证所有 ElGamal 秘诺,证明他们的秘诺没有破解绑定性,就可以启用秘诺切换(通过软分叉)。 但这种情况下用户仍有选择: - 用户可决定继续创建新交易。即使因为 ElGamal 秘诺方案仅为计算隐匿,有可能破坏隐私性(只对**上一个** UTXO),但用户至少仍旧可以存取自己的币。 - 或者用户可决定不管钱,不做任何交易(但是保留隐私性,因为他们的交易仅验证有完美隐匿性的 Pedersen 秘诺) 有些情况下,隐私泄露对某个人的生命安全威胁要高过一定加密货币的损失。但决策权应该留给个人用户,秘诺切换就实现了这种选择。 需要明确的是,这一安全措施只有在遇到意外灾难的情况下才会启用。若计算有所进步,离散对数难题受到质疑,那包括加密货币在内的众多其他加密系统都需要紧急更新原语,抵抗未来潜在威胁。秘诺切换只是在 Pedersen Commitments 被意外破解情况下,提供额外的安全保护方案。