orangeitems’s diary

クラウドではたらくエンジニアの日々の感想です。

仮想通貨の階層的決定性ウォレット(HDウォレット)の致命的なリスクを考える(2018/2/22修正)

f:id:orangeitems:20180128120023j:plain

なぜ1つの秘密鍵を盗んだだけで全口座分を盗めたのか

コインチェック問題については、マルチセグやウォレットの件が非常に有名になりました。ただ、下記のような疑問が浮かばなかったでしょうか。

各口座には、専用のウォレットがあり管理されているはず。それぞれ別の秘密鍵であるので、シングルセグであってもホットウォレットであっても、なぜ一括で出金できたのか。

26万口座がNEMウォレットを持っていたので、26万の秘密鍵があったはず。これを一括で引き落とすのは難しいのではないか。

コインチェックを含め仮想通貨取引所の口座を持つと、特定の仮想通貨用のウォレットが作成されます。その中に秘密鍵が作成され、それをもとに公開鍵が作成されます。そして、その公開鍵を利用してアドレスを作成します。このアドレスから入送金を行うわけです。アドレスは毎回使い捨てです。

ウォレット→秘密鍵→公開鍵→アドレス

という順番です。かつ、仮想通貨ごとに微妙に仕様が違います。また、ウォレットの中には仮想通貨は入っていません。仮想通貨の情報はブロックチェーンと呼ばれる参加者全体で保持する共有ストレージに保管されています。そこに秘密鍵を使ってアクセスするという仕組みです。

したがって、コインチェックのウォレットが1つしかなく、そこに全額入っていたから、ということのはこの理屈ではあり得ないのです。

でも、まるで1つのウォレットから抜き出されたような状況になっています。私の疑問はここでした。

スポンサーリンク

 

理由

この仕組みを説明するには、「階層的決定性ウォレット」もしくは「HD(Hierarchical Deterministic)ウォレット」という言葉を知る必要があります。

HDウォレットという言葉を使って説明します。

なお、下記の記事が最も正しく説明されていますのでこちらから一部引用いたします。詳細に知りたい場合は、下記をご参照ください。グノシー社のブログです。

blockchain.gunosy.io

 

HDウォレットは、1つの「シード (Seed) 」と呼ばれる値から秘密鍵を生成し、階層構造を用いて管理するウォレットのことです。

階層構造を用いて管理するウォレットのことです!

大事なことなので大声で言いました。

怖い解説があります。

HDウォレットでは1つのシードから階層的に鍵を実質無限に生成できます。

(中略)シードがあれば何度でもHDウォレットを再構築することが可能です。階層構造の仕組みにより管理すべき対象が1つのシードに絞られるため、ランダムウォレットのように秘密鍵を複数保持して管理する責任から解放されます。

実際には鍵の生成過程で秘密鍵が生成されるので保持管理し続けますが、注力して管理すべきものが「シード」のみになるので管理コストが大幅に下がるというわけです。

逆にシードが他人に知られてしまえばウォレットを再構築されてしまい、自分が保有するビットコインの全てを支配されてしまうリスクが生まれます。

これはHDウォレットの欠点でもあります。

さらに、 

先ほどのGunosy Blockchain Blogより、決定的な図を引用します。

f:id:orangeitems:20180128125818p:plain

 

ウォレットアカウント・・・ウォレットチェーン・・・

マスターノードを使えば、全口座引っこ抜けますね。。。

また、恐ろしい話で、シードからマスターノードの秘密鍵は再生成できますから、

 

コインチェックの問題は、ここが本質です。26万人分の口座は1つのシードから生成された孫ウォレットだったということです。

他の取引所も、同じような仕組みの可能性が高いです。

追記(2018/2/22)

この部分は修正します。 もちろん、シードを入手すればその配下のアカウントについては秘密鍵を入手できるので脆弱性が以前としてあります。一方で、今回のコインチェックの問題は、単一アドレスから送金されていますので、複数のアカウントをハッキングしたわけではありません。したがって、HDウォレットの危険性から来る問題ではなく、単に「顧客の資産を1つのアカウントの1つのウォレットチェーンでマージして運用していた」ということになると思います。

 

さて、Gunosy Blockchain Blogに、

シードを誰かに知られた場合、関連したビットコインは全て盗まれてしまう

こんなことが書かれていますね

 

対策

こんな話を聞くと、取引所に預けておくのはどうなのか、という気持ちになると思います。ローカルに持った方が安全、それも一理あると思います。

マルチセグにすれば安全、コールドウォレットなら安全という以前に、1つのシードで全額が管理できてしまう仕組みこそ脆弱だと思いませんか?

例えば1つのシードで扱う最大金額を決めておけば、それ以上流出しないわけです。5億NEMを管理したければ、100万NEMを最大値として決めておき、それ以上は別のシードで管理する。そうして50シードを管理するようにしておけば、少なくとも1回の被害は100万NEMに収まります。

 

システムの全体設計に問題がありそうだと思った今回の発見でした。

 

追記(2018/2/22)

この記事について、「今回のコインチェックの件はHDウォレットの脆弱性の話ではなく、単一のウォレットにて顧客資産をマージして運用していたからでは」というご指摘を頂きました。BIP32やBIP44の原文も確認しました。

bips/bip-0032.mediawiki at master · bitcoin/bips · GitHub

bips/bip-0044.mediawiki at master · bitcoin/bips · GitHub

1つのHDウォレットにおいて、確かに各アカウントに分岐した後は、アドレスは独立しておりこの仕組みにおいては1つのウォレットから全部のアカウントを盗み出すには、アカウントごとにアドレスを発行する必要があります。

ということで、1つのアドレスから不正送金できてしまったことから、HDウォレットのせいではない、ということがわかりました。1つのアカウントまたはウォレットに全顧客の資産を入れておくのは、余計危ないとは改めて思いました。

ご指摘いただいた方、ありがとうございました。

なお、「1つのHDウォレットで全顧客をアカウントとして取り扱い」取引所が運営されている場合、このリスクは残ると思いますので、記事としては残したいと思います。