[翻译]BIP146 解决签名编码的延展性

2022-08-20 10:53:34 浏览数 (3)

综述

本提案描述了改变比特币交易的验证规则,来修正与ECDSA签名编码有关的交易延展性。

动机

签名延展性指的是:网络中的任何中继节点,不需要获取对应交易的私钥, 而修改该交易签名的能力。对于非SW交易,签名延展性将改变txid,将使所有未确认的子交易失效。即使SW交易(BIP141)的txid是非第三方延展的,但这种延展性的vector仍然将改变wtxid,并且可能降低紧凑型区块的中继效率(BIP152)。

自从严格的DER签名实施后,ECDSA签名中还有两个已知的延展性来源:

  • ECDSA自身的签名延展性:ECDSA签名是自身具有延展性,因为内部S的负值(模曲线顺序)不会使签名无效。
  • 无效签名的延展性:如果采用OP_CHECKSIG 或OP_CHECKMULTISIG 的签名验证失败,一个false将被返回到栈上,并且脚本验证将继续执行。无效签名可以使用任何值,只要这些值遵循BIP66 中描述的所有规则。

本提案定义了新的规则来修正上述提到的延展性。

规则

为了修正签名编码的延展性,接下来的新规则被应用到当下的隔离验证和隔离验证脚本。

LOW_S

新规则要求ECDSA签名内的S的值最大是曲线半径除以2(实际上将该值限制在其下半部分范围内)。每个使用了OP_CHECKSIG1,OP_CHECKSIGVERIFY,OP_CHECKMULTISIG,OP_CHECKMULTISIGVERIFY操作码的签名,同时该签名采用了ECDSA验证,则必须使用一个介于0x1和0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,并且采用严格DER编码的S值。

如果传递给ECDSA验证的签名没有通过LOW_S 检查,并且是一个非空的字节数组,则整个脚本评估立即失败。

在签名中一个高S值可以平滑的被S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S 替换。

NULLFAIL

如果一个OP_CHECKSIG试图向栈上返回一个false值,那我们要求对应的签名必须是一个空的字节数组。

如果一个OP_CHECKMULTISIG试图向栈上返回一个false,我们要求传输到OP_CHECKMULTISIG的所有签名必须是空的字节数组,即使由于过早的签名验证中断而可能导致一些签名处理被跳过。

否则,整个脚本评估立即失败。

示例

接下来的示例由LOW_S和NULLFAIL2 规则组成。

符号:

代码语言:javascript复制
CO       : curve order = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
HCO      : half curve order = CO / 2 = 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0
P1, P2   : valid, serialized, public keys
S1L, S2L : valid low S value signatures using respective keys P1 and P2 (1 ≤ S ≤ HCO)
S1H, S2H : signatures with high S value (otherwise valid) using respective keys P1 and P2 (HCO < S < CO)
F        : any BIP66-compliant non-empty byte array but not a valid signature

这些脚本像以前一样返回TRUE至栈上:

代码语言:javascript复制
S1L P1 CHECKSIG
0 S1L S2L 2 P1 P2 2 CHECKMULTISIG

这些脚本像以前一样返回FALSE至栈上:

代码语言:javascript复制
0 P1 CHECKSIG
0 0 0 2 P1 P2 2 CHECKMULTISIG

在新规则执行后,先前的TRUE脚本将立即失败

代码语言:javascript复制
S1H P1 CHECKSIG
0 S1H S2L 2 P1 P2 2 CHECKMULTISIG
0 S1L S2H 2 P1 P2 2 CHECKMULTISIG
0 S1H S2H 2 P1 P2 2 CHECKMULTISIG

在新规则执行后,先前的TRUE脚本将立即失败

代码语言:javascript复制
  F P1 CHECKSIG
  0 S2L S1L 2 P1 P2 2 CHECKMULTISIG
  0 S1L F   2 P1 P2 2 CHECKMULTISIG
  0 F   S2L 2 P1 P2 2 CHECKMULTISIG
  0 S1L 0   2 P1 P2 2 CHECKMULTISIG
  0 0   S2L 2 P1 P2 2 CHECKMULTISIG
  0 F   0   2 P1 P2 2 CHECKMULTISIG
  0 0   F   2 P1 P2 2 CHECKMULTISIG

部署:

该BIP将通过BIP9(版本位)进行部署。

比特币主网络中,BIP9的开始时间是:midnight TBD UTC(纪元时间戳TBD),BIP的结束时间是:midnight TBD UTC(纪元时间戳TBD)。

比特币测试网络中,BIP9的开始时间是:midnight TBD UTC(纪元时间戳TBD),BIP的结束时间是:midnight TBD UTC(纪元时间戳TBD)。

兼容性

从v0.9.0,客户端已产生了LOW_S兼容性脚本,并且从v0.11.1客户端开始,LOW_S规则已经作为中继策略被强制执行。截止2016年8月,违反上述规则的交易很少被添加至主链中。对于实际使用的所有scriptPubKey 类型,非兼容性的签名可以平滑的被转换为兼容性,所以这些新规则并没有任何导致任何功能的丢失。

使用 OP_CHECKSIG or OP_CHECKMULTISIG失败的脚本很少出现在主链上。从v0.13.1客户端开始,NULLFAIL 规则已经作为中继政策被强制执行。

当设计新脚本时,用户必须注意这些新规则。

实施

参考客户端的实现可以在下述网址获得:github/interpreter.cpp 和 github/pull

脚注

  1. P2WPKH的交易在BIP141中描述
  2. 请注意由于v0.13.1客户端中具体实现的细节,一些使用高S值的签名通过了LOW_S检测。然而,这些签名肯定是无效的,由随后的NULLFAIL检测失败。

引用

BIP146原文 : https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki ECDSA博文 : http://www.instructables.com/id/Understanding-how-ECDSA-protects-your-data/


本文由 Copernicus团队 姚永芯翻译,转载无需授权。

0 人点赞