Mt.Goxに使われた脆弱性、トランザクション展性とは?

「システムに弱いところがあってビットコインがいなくなった」?

ここまで解説してきた知識から、実際にニュースに登場するBitcoinの問題を理解できるということを見ていこう。

ここでは、Mt.Goxの攻撃に使われたとされる、Bitcoinシステム全体の脆弱性、Transaction Malleability(トランザクション・マレアビリティー、トランザクション展性)問題について解説する。

Mt.GoxのCEOが会見で口にした、「システムに弱いところがあってビットコインがいなくなった」というふざけた説明をはじめとして、なかなか詳細に語られることの少ない「トランザクション展性」問題だが、このサイトを通してBitcoinの実装の詳細を学ばれた方は、これがとても単純な問題であり、巨額のコインがお粗末とも言うべき理由によって喪失したという事に驚かれることであろう。

(しかしながら、Mt.Goxの破綻の原因については諸説あり、Mt.Gox側の主張を完全に信用する訳にはいかないのが現状である。参考:Bitcoin Transaction Malleability and MtGox(PDF、英語))

電子署名の正当性を保ったままのトランザクションの改ざん

Bitcoinウォレットを実装するを読まれた方は、電子署名の検証方法が複雑であり、署名に複雑なスクリプトが用いられていることが分かると思う。これのせいで、署名の正当性を保ったまま、同等の意味を持つトランザクションが、複数通りのトランザクションハッシュ(ハッシュはトランザクション全体について取られている事に注意)を持ちうる。これが「トランザクション展性」である。

この問題で、広く「展性」という訳が用いられているため、この記事でも「展性」の訳を用いたが、これは誤訳であるように感じる。malleableをオックスフォード現代英英辞典で引くと、"that can change; likely to change"と書いてある。筆者としては、より正しい理解を広めるため、「トランザクション変形性」「取引変形性」といった訳を提唱したい。

トランザクションの改ざんを行い、ハッシュを変えた同等のトランザクションを先にブロックチェーンに取り込ませることで、Mt.Goxのように、トランザクションのハッシュのみを検証している甘い実装では、トランザクションがブロックチェーンに取り込まれないまま宙に浮いたと解釈させることができた。これにより、何度もトランザクションの再送をさせることができたのが、今回のコイン喪失の原因であったと思われる。

signature_scriptとpk_script

Bitcoinの「スクリプト」はとても複雑であり、Bitcoinウォレットを実装するにおいては、軽く触れるにとどめた。

Bitcoinのスクリプトによる署名の検証は、tx_inのsignature_scriptとtx_outのpk_scriptを結合して、スタック言語のバイトコードとして実行することによって行われる。

一般に、tx_outのpk_scriptは公開鍵のハッシュ値を含むのに対して、tx_inのsignature_scriptは、ECDSAの実際の公開鍵と電子署名を含む。

実際のスクリプトは以下のように実行される:

スタック スクリプト 説明
(空) <署名> <公開鍵> OP_DUP OP_HASH160 <公開鍵のHash160> OP_EQUALVERIFY OP_CHECKSIG signature_script + pk_script
<署名> <公開鍵> OP_DUP OP_HASH160 <公開鍵のHash160> OP_EQUALVERIFY OP_CHECKSIG
<署名> <公開鍵> <公開鍵> OP_HASH160 <公開鍵のHash160> OP_EQUALVERIFY OP_CHECKSIG アイテムを複製
<署名> <公開鍵> <公開鍵のHash160> <公開鍵のHash160> OP_EQUALVERIFY OP_CHECKSIG アイテムのHash160を取る
<署名> <公開鍵> <公開鍵のHash160> <公開鍵のHash160> OP_EQUALVERIFY OP_CHECKSIG tx_inの公開鍵とtx_outの公開鍵のハッシュが一致することを確認
<署名> <公開鍵> OP_CHECKSIG 署名を検証
true (空) 検証が成功

txにおいて電子署名されるデータに含まれないのはtx_inのsignature_scriptのみであるから、どちらもsignature_scriptこれを改ざんする攻撃であるが、改ざんする場所が異なる。

(tx_in, tx_outなどについてはBitcoinウォレットを実装するで復習してほしい)

1つ目の改ざん方法:署名本体の改ざん

OpenSSLの電子署名の検証は、必ずしも仕様を遵守していない電子署名であっても受け付けてしまうという問題がある。これが署名本体の改ざんである。これにより、トランザクションのハッシュを変化させることができてしまう。

2つ目の改ざん方法:署名スクリプトの改ざん

2つ目は電子署名スクリプトの検証である。先に説明したように、これはスタック言語のバイトコードであるから、署名検証に影響しないように余計なバイトコードをsignature_scriptに付与することで、同様にトランザクションのハッシュを変化さられてしまう。

責任は誰にあるのか

第一の責任がMt.Goxにある事は疑う余地のない事実であろう。仮にこのようなバグが存在していたとしても、規模があまりにでかすぎるというのもあるし、上で説明した通り、バグとしてもあまりにお粗末な内容である。

しかしながら、Bitcoinの設計上の問題だとする声が少ないことには違和感を感じる。

Bitcoinは「Simplified Payment Verification」が原著論文で提案されながら、長らく実装方法が存在しなかった事などをはじめとして、Satoshi Nakamoto本人が様々な機能を構想しておきながら、その多くを本人は実装しないまま今に至る感が否めない。 署名検証に不要な拡張性が付与されていれば、様々なトラブルを引き起こしうるという事は当初から予測できたことだろう。

Bitcoinの暗号通貨としての設計上の問題は数多く指摘されているが、通貨供給量の問題のような哲学的な問題ではない、些細な設計上の問題が、通貨全体を揺るがす事態へと繋がる可能性もあるということを覚えておきたい。

Bitcoinの派生通貨」につづく