Segwitに関して調べた記録3
前回の続き
3,Segwitとトランザクション展性攻撃耐性に関して
Segwitがもたらしてくれる恩恵として「トランザクション展性攻撃の耐性が増す」ということをよく言われ、それがライトニングネットワークを実現するのに必要だと言われている。
トランザクション展性攻撃(はじめに)
トランザクション展性攻撃耐性に関して書く前に、そもそもトランザクション展性攻撃って何だ、どういった手法で攻撃するんだ、という話をしておかなくてはいけないと思う。
ビットコインはtx_outに書かれているロックスクリプトを解錠するための署名を行うとき、自分が新たに作成するtxの署名スクリプト以外の要素にロックスクリプトを加えたものををシリアライズしてそれに署名を行う。
つまり、署名によって守られるのは参照しているロックスクリプトと、署名用スクリプト"以外の"トランザクションの要素となる。署名用スクリプトが本当に署名者が作成したものかどうかを判定する仕組みは無いのだ。
そして署名用スクリプトを含む新たに生成されたトランザクションは署名検証が通りさえすればそれが正式なものとしてブロックに格納される。
この仕組みを悪用して他人が生成したトランザクションのIDを変えてしまうのがトランザクション展性攻撃と呼ばれる攻撃だ。
トランザクション展性それそのものの意味はもっと広義の意味があるので、たまたまHash値が衝突してしまうものもトランザクション展性であり、そちらを使った攻撃もできなくはないが、ここでは無視する。
トランザクション展性攻撃(攻撃方法)
ここでは実際に使われた攻撃方法を紹介する。おそらくこれが一般的で(攻撃を一般的と言って良いのか分からないが)簡単で確実な攻撃方法だ。
この攻撃で攻撃者は下記の手順で「tx_idは違うが署名検証は正常に通過する攻撃用コピートランザクション」を作成して攻撃する。
- 攻撃対象者がブロードキャストした、まだブロックに格納されていないトランザクションを取得する。
- 署名スクリプト以外に触れると、署名が通らなくなるので、署名スクリプトを書き換える。この時、元の署名スクリプトと「書き方は異なるが同じ意味を持つスクリプト」に書き換える。
- 攻撃用コピートランザクションをネットワークに投げる
- マイナーが攻撃者が生成した攻撃用コピートランザクションをブロックに入れれば攻撃は成功。元のトランザクションは棄却されるのでブロックに入ることはない。
この攻撃をすることで、攻撃対象者が本来意図していない形にトランザクションが形を変え、ブロックに格納されてしまうことになる。
トランザクション展性攻撃(被害)
さて、攻撃方法は分かったがこの攻撃、攻撃された側はなにか困るのか?という疑問がある。送金先が変えられたわけでも送金料が変えられたわけでもない。ただ、トランザクションIDが変わっただけだ。
実際、単にこの攻撃をするのは現状としてほぼ無意味である。しかし、ある条件下ではこの攻撃が脅威になり得る。それは例えば以下の通り。
- 送金の確認を自分が生成したトランザクションIDだけを追って確認していた場合
- ブロックに格納される前のトランザクションを参照して新たにトランザクションを生成したい場合
1について、これが実際の被害となって現れたのがあの「Mt.GOX事件」だ。マウントゴックスは取引所からの送金をトランザクションIDを追って確認していただけで、きちんと送金のたびにシステムをビットコインネットワークと同期させて、実際に手元にあるお金がどうなっているのか、逐一照合して確認を取っていなかったのだ。
2について説明する前にまず、トランザクションのtx_inの中身を思い出していただきたいのだが、tx_inにはout_pointと呼ばれる参照先のトランザクションIDとその中で自分が参照したいtx_outをインデックス番号で示すフィールドがある。
では、ブロックに格納される前のトランザクションを使用しようとして、新たにトランザクションをネットワークに投げたとする、何も起こらなければ先に投げたトランザクションが承認された後、そのトランザクションを参照しているトランザクションが続いて承認される。
しかしここで、参照先のトランザクションが展性攻撃を受けると、新たに生成したトランザクションは参照先を失ってそれそのものが無効なトランザクションとなってしまうのだ。
トランザクション展性の被害は上記以外にもパターンはあると思うが、要するにトランザクションIDが作成者の意図しないIDに変えられてしまうことが原因で発生する問題が起こりえるという話だ。
Segwitとトランザクション展性攻撃耐性
以上を踏まえて、やっと本題。だが、実はもう前回の記事でここの部分はほとんど書いてある。Segwitは署名スクリプトをwitnessとして分離する。このwitnessはトランザクションIDを計算するときに使用されないので、witnessに変更が加えられたとしても、トランザクションIDは変えられない。そのため、上記で書いたような「署名スクリプトを別の言葉で同じ意味になるように書き換える」という攻撃方法が出来なくなる。
上記以外にもトランザクション展性攻撃は可能だが、少なくとも(後述するP2WPKHやP2WSHを素直に使った場合は)上記の攻撃への耐性はついたことになる。
また、開発者にとってトランザクションIDだけを追えば良いというのは仕事の助けになる。なぜなら送金のを確認する度にノードをブロックチェーンと同期させてトランザクション展性攻撃を受けていないか確認しなくても良くなるからだ。
〜4へ続く〜
私感など(関係ないことも含む)
Witnessプログラムについては後で書くけども、少なくともバージョン0のWitnessプログラムでは「Witness部分を同じ意味になるように書き換える」ということが出来ないっぽい(制限が大きいので)。大きい構造的に、というのと、細かい仕組みの中(バージョン0内)との二重でブロックが効いて署名の書き換えはできなくなりそう。というか、きっと出来ないんだろう。
これも後から書く事になると思うけど(忘れていなければ)、Witnessプログラムって新たなバージョンを追加した時に後方互換しやすいように前もって対策が打ってある。なので、署名に関する変更であればSegwit採用以降はソフトフォークで結構何でも追加できるようになると思う。
(これは、量子耐性を持った暗号を新たに採用するときなどに都合が良いと言われている)