背景图

BIP-62处理延展性攻击

这篇文档主要是解决比特币的延展性攻击。

交易的延展性,也被称作为是可锻性,啥叫可锻,也即同样一个东西(如一坨金属),它的本质和质量都没有改变,但是它的形状改变了。而这个可锻性,会造成交易ID——TXID的不一致,从而导致用户找不到发送的交易。因为交易的ID就是指交易的hash值。但是由于隔离见证的使用,导致脚本不再是交易结构的一部分(但是逻辑上还是一样的),这样这个扩展性问题就不那么重要了。但是如果旧节点产生的交易,可能还是要使用这样的规则去杜绝扩展性。

注意:本文档是一项正在进行的工作,并未完成,实施或以其他方式适用于部署。

抽象

该文件规定了对比特币交易有效性规则的建议修改,以便不可能延展交易的可塑性(至少在交易发送者不选择避开它时)。

版权

此BIP根据2条款BSD许可证进行许可。

动机

截至2014年2月,比特币交易在多个方面具有延展性。这意味着(有效)交易可以在传送中被修改,而不会使其失效,但无法访问相关私钥。

这个问题有多种原因:(感觉这里讲的就是如果同一个输出,发送者发送多笔花费这个输出的交易会怎么样?

  • 交易被改后,交易发送者可能无法识别他自己的交易。(因为TXID可能被修改了,链上使用旧的txid是无法找到这笔交易的)
  • 交易发送者可以花费由原始交易创建的更改的交易。如果修改后的交易被矿机开采,这将变为无效。
  • 修改后的交易实际上是双重花费,可以在没有恶意的情况下(发送者)创建,但易于被用于其他攻击。

已知几种延展性来源(主要是指哪些部分可以被修改,修改什么):

  1. 现在的非DER编码的ECDSA签名. 比特币参考客户端使用OpenSSL来验证签名。由于OpenSSL接受的不仅仅是严格遵守DER标准的序列化,而且还是可延展性的来源。自v0.8.0以来,非DER签名不再被中继。(就是说DER签名可以解决问题,非DER签名的交易会有问题。)
  2. scriptSig中没有推送操作。 在scriptSig中脚本操作的任何序列号都会导致预期的数据推送,但不仅仅是推送该数据,会产生具有相同有效性的替代事务。
  3. scriptSig中非标准尺寸的推送操作。 比特币脚本语言具有多个推式运算符(OP_0,单字节推送,最多75字节的数据推送,OP_PUSHDATA1,OP_PUSHDATA2,OP_PUSHDATA4)。由于后者与前者具有相同的结果,它们会带来更多的可能性。(容易遭受DDOS攻击,推送大数据也会导致mempool内存爆满)
  4. 零填充数字推送。 在scriptPubKey操作码使用被解释为数字的输入的情况下,它们可以被填充为零。
  5. 内在的ECDSA签名延展性 ECDSA签名本身已经具有延展性:取数字S的负数(以曲线顺序为模)不会使其无效。(这个需要了解椭圆曲线的特性了,对称的点也在曲线上的
  6. 多余的scriptSig操作。 在脚本开始处添加额外的数据推送,这些数据不会被相应的scriptPubKey消耗,这也是可延展性的来源。(一开始压入一些数字,如果栈不被清空会有很多的问题)
  7. 输入被脚本忽略。 如果scriptPubKey以OP_DROP开头,例如,相应脚本的最后一次数据推送将始终被忽略。
  8. 基于Sighash标志的掩码。 Sighash标志可用于在签名时忽略脚本的某些部分。(修改sighash,这个可以查看DER的结构)。
  9. 交易发起者的新签名。 交易发起者(或任何可以访问相关私钥的人)总是能够创建新的签名,这些签名将相同的输入用于相同的输出。

前六个和第七个的一部分可以通过额外的共识规则来解决,但最后两个不能。无法修复#7意味着即使有了这些新的共识规则,也将始终有可能创建支出交易全都具有延展性的输出。然而,当限制使用一套安全的输出脚本时,额外的共识规则可以使支出交易选择性地不可延展(如果花费者选择;因为他自己总是可以绕过#8和#9)。

规范

新规则

引入了七个额外的规则,以准确地与上面列出的七个可延展性来源进行对比:

  1. 标准的ECDSA编码签名。 传递给OP_CHECKSIG,OP_CHECKSIGVERIFY,OP_CHECKMULTISIG或OP_CHECKMULTISIGVERIFY的ECDSA签名必须使用严格的DER编码进行编码。为了为OP_CHECKSIG和OP_CHECKMULTISIG故意创建无效签名提供一种紧凑的方式,还允许使用空字节数组(即OP_0的结果)。使用非DER签名进行验证会使整个脚本评估为False(而不仅仅是签名验证)。请参阅参考资料:DER编码
  2. scriptSig中的非推送操作。 ScriptSig中只允许数据推送。评估任何其他操作会使脚本评估为false。请参阅参考:推送运算符
  3. scriptSig中的推送操作是非标准大小类型。 尽可能使用尽可能最小的脚本操作。使用可以用较短方式编码的操作推送数据会使脚本评估为false。请参阅参考:推送运算符。
  4. 零填充数字推送。 任何时候脚本操作码都会消耗一个被解释为数字的堆栈值,它必须以尽可能最短的形式进行编码。’负零’是不允许的。请参阅参考:数字。
  5. 固有的ECDSA签名延展性。 我们要求ECDSA签名内的S值至多是曲线次序(就是n的值)除以2(实质上限制该值到其下半部分范围)。请参阅参考:签名中的低S值
  6. 多余的scriptSig操作。 scriptPubKey评估将需要导致一个非零值。如果任何额外的数据元素保留在堆栈上,则脚本评估为false。
  7. 脚本忽略输入 OP_CHECKMULTISIG和OP_CHECKMULTISIGVERIFY消耗的(不必要的)额外堆栈元素必须是空字节数组(OP_0的结果)。其他任何事情都会使脚本评估为false。

区块有效性

为了在网络中引入这些新规则,我们添加了v3块和v3交易。交易跳过v2以使交易和​​区块规则之间的版本号保持同步。v2交易的处理与v1交易相同。使用与BIP 0034相同的机制来引入v3块。当过去1000个block中有75%是v3时,会激活一个新的共识规则:

  • v3块中的所有交易都必须遵守规则#1-#2。
  • v3块中的v3(或更高)交易也需要遵循规则#3-#7。

当过去1000个块中的95%为v3或更高时,v2块将完全失效。但请注意,v1(和v2)交易永远保持有效。

参考

以下是签名,编码和数据推送效果的总结。

签名中的低位S值

签名中的值S必须介于0x10x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0(含)之间。如果S太高,只需将其替换为S'= 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S.

不保证OpenSSL库生成的签名与此约束一致。参考客户端的0.9.3版本提供了检测和纠正的示例。

值R的约束与ECDSA不变,其值可以在0x10xFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140(含)之间。

DER编码

作为参考,这里是如何正确编码DER格式的签名。

格式如下:

1
0x30 [总长度] 0x02 [R长度] [R] 0x02 [S长度] [S] [sighash型]

  • 总长度:后面所有内容的1字节长度描述符,不包括sighash字节。
  • R长度:后面的R值的1字节长度描述符。
  • R:任意长度的大端编码的R值。它不能以任何0x00字节开始,除非接下来的第一个字节是0x80或更高,在这种情况下需要一个0x00。
  • S长度:接下来的S值的1字节长度描述符。
  • S:任意长度的大端编码的S值。与R相同的规则适用。
  • sighash类型:1字节散列类型标志(只允许0x01,0x02,0x03,0x81,0x82和0x83)。

参考客户端自0.8.0版本开始实施(仅作为中继策略,而不是作为共识规则)。
该规则与上面的低S要求相结合导致S长度最多为32(并且R长度最多为33),并且总签名大小最多72字节(平均71.494字节)。

推动操作

  • 推空的字节序列必须使用OP_0。
  • 通过0x10推送一个1字节的字节序列0x01必须使用OP_n。
  • 推送字节0x81必须使用OP_1NEGATE。
  • 推送任何其他高达75字节的字节序列时,必须使用正常的数据推送(操作码字节n,其中n是字节数,紧接着推送n字节的数据)。
  • 推送76到255个字节必须使用OP_PUSHDATA1。
  • 推送256到520字节必须使用OP_PUSHDATA2。
  • OP_PUSHDATA4永远不能使用,因为不允许超过520个字节,下面的操作可以使用其他操作符完成。
  • 任何其他操作都不被认为是push。(意思就是不能使用数字这样直接做推送

数字

堆栈元素的本地数据类型是字节数组,但有些操作将参数解释为整数。使用的编码是带有明确的符号位(最后一个字节的最高位)的小端。数字的最短编码是(以())之间的十六进制给出的范围边界编码。

  • 0:OP_0; (00)
  • 1..16:OP_1..OP_16; (51)..(60)
  • -1:OP_1NEGATE; (79)
  • -127 ..- 2和17..127:正常的1字节数据推送; (01 FF)..(01 82)和(01 11)..(01 7F)
  • -32767 ..- 128和128..32767:正常的2字节数据推送; (02 FF FF)..(02 80 80)和(02 80 00)..(02 FF 7F)
  • -8388607 ..- 32768和32768..8388607:正常的3字节数据推送; (03 FF FF FF)..(03 00 80 80)和(03 00 80 00)..(03 FF FF 7F)
  • -2147483647 ..- 8388608和8388608..2147483647:正常的4字节数据推送; (04 FF FF FF FF)..(04 00 00 80 80)和(04 00 00 80 00)..(04 FF FF FF 7F)
  • 任何其他数字都不能被编码。

特别要注意的是,如果允许使用非最短格式,则零可以编码为(01 80)(负零)。

兼容性

交易中继发布了一个新的节点软件版本,它使v3交易标准化,并在scriptSigs满足上述规则时中继它们。v1交易的中继不受影响。支付v3交易创建的输出的v1交易也不受影响。

电子钱包更新由于v3交易目前是非标准的,因此无法立即开始创建它们。可以检查软件以确认新的规则,但只有当网络的重要部分已升级到兼容的代码时才能启动v3。它的意图是“我希望这个交易受到延展保护”,并且仍然是钱包软件的选择。

参考和引用

比特币的交易延展性指的是什么?
交易的构造、签名与广播
比特币中交易延展性问题
交易延展性 | Transaction Malleability
Transaction Malleability
bips/bip-0062.mediawiki

0%