SegwitのOP_CHECKSIGにはバグがある
「バグ」と言っても、勘違いによってセマンティクスを意図せず変更してしまったという話であって、脆弱性とかではないです。
前提
- 秘密鍵と公開鍵の組があるとする。
- ある取引があり、その中のある入力をとする。
- の中にと同じインデックスをもつ出力は存在しないとする。
- の親出力はでロックされているとする。
Pre-segwitの場合
の親出力をアンロックするためには、を用いて固定値0x00...01
の署名を生成する必要がある1。にはこの入力と同じインデックスをもつ出力は存在しないという情報しかコミットされていない。したがってを手に入れた攻撃者は、出力数より入力数が多い取引を構築することによって、でロックされている任意の出力(の親出力以外も)を盗むことができる。
Segwitの場合
の親出力をアンロックするためには、を用いてoutpoint
をコミットした署名を生成する必要がある2。ゆえにこの署名は、少なくともoutpoint
で指定された出力をアンロックするためにしか使えない。
BIP-143の間違い
SegwitにおけるOP_CHECKSIG
のアルゴリズムを規定したBIP-143には次のような記述がある3。
In the original algorithm, a
uint256
of0x0000......0001
is committed if the input index for aSINGLE
signature is greater than or equal to the number of outputs. In this BIP a0x0000......0000
is committed, without changing the semantics.
著者は”without changing the semantics”と述べているが、上述したようにセマンティクスは変化してしまっている。