見出し画像

HDウォレットのセキュリティを向上させる|詳解ビットコイン⑦

『詳解ビットコイン』(Kalle Rosenbaum著、オライリージャパン)を読んでいます。その個人的なまとめとして書いていきます。

拡張秘密鍵で木構造を作ることの問題

HDウォレットでは、親の拡張秘密鍵を使って木構造を作っていけます。この性質を利用すると、ビットコイン関連サービスを効率よく提供できます。

例として、仮想通貨取引所サービスの運営について考えます。仮想通貨取引所ではユーザーごとにビットコインアドレスを作っていく必要があり、それは大変な作業です。そこで、運営者は取引所のサーバにm/0の拡張秘密鍵を置くことにします。こうすれば、m/0/0、m/0/1、さらにm/0/0/0、m/0/0/1とアドレスを自動で作っていけて便利です。

しかし、サーバに拡張秘密鍵を配置しておくことには危険が伴います。悪意のある者がサーバに不正アクセスし、拡張秘密鍵(m/0)を知ったら、その子に当たるアドレスの秘密鍵はすべて算出されてしまいます。

不正アクセスについては、以下の説明がわかりやすかったです。
https://www.cybersecurity.metro.tokyo.lg.jp/ghost/ghost3/index.html
https://www.cybersecurity.metro.tokyo.lg.jp/column/ep17/

拡張公開鍵からも作ればよりセキュア

木構造は拡張公開鍵(xpub)というものからでも作っていけます。

拡張公開鍵(xpub)とは、公開鍵とチェーンコードから構成されものです。拡張公開鍵によって木構造を作っていけば、よりセキュアにサービスを提供できる可能性があります。

拡張公開鍵を使って木構造を作っていくなら、サーバには拡張秘密鍵の代わりに拡張公開鍵を置きます。

この場合、サーバに置いた拡張公開鍵が他人に知られるリスクがあります。もし拡張公開鍵が他人に知られたら、その公開鍵の子にあたるアドレスや公開鍵を知られてしまうことになりますが、秘密鍵は知られません。つまり、拡張公開鍵が知られたとしても、それだけでお金を盗まれることはありません。

拡張公開鍵で木構造を作っていく流れ

拡張公開鍵で以下の木構造を作っていく流れを記載します。

①マスター拡張秘密鍵を生成する

拡張公開鍵で木構造を作るにあたって、拡張公開鍵を作る必要があります。ここではマスター拡張公開鍵を作る方法から説明していきます。

大まかな流れとしては以下のようになっていて、マスター拡張公開鍵を作るには、マスター拡張秘密鍵が必要です。

そこで、まずはマスター拡張秘密鍵を生成します。その手順は以下の通りです。

乱数のシードをHMAC-SHA-512という暗号学的ハッシュ関数で処理をして、その出力の512ビットを前半と後半に分けます。

出力の前半部分はマスター秘密鍵として、後半部分はチェーンコードとして取り扱い、ふたつを合わせればマスター拡張秘密鍵となります。

②マスター拡張公開鍵を生成する

マスター拡張秘密鍵は、マスター秘密鍵とチェーンコードに分けます。

マスター秘密鍵は公開鍵生成関数で処理します。その結果、マスター公開鍵が得られます。チェーンコードはそのまま使います。

③子の拡張公開鍵を生成する

子の拡張公開鍵は、親の拡張公開鍵から作ります。

まずは親の公開鍵とチェーンコード、インデックス(ここでは「0」)をHMAC-SHA-512でハッシングします。

出力の前半部分は秘密鍵のように扱い、公開鍵を作ります。その公開鍵を親の公開鍵とで「特別な加算」を行うと、子の公開鍵ができます。

「前半部分を秘密鍵のように扱い、公開鍵を作る」という部分は、詳解ビットコインにあった文をそのまま持ってきました。前半部分を公開鍵生成関数で処理しているのかとも思いましたが、わざわざこのような表現を使うということは、結構ややこしいことをしているのかもしれません。

続いて出力の後半部分についてですが、後半部分はそのままチェーンコードとして使うことができます。そのため、特に何か処理が必要なわけではありません。

前半部分から作った子の公開鍵と、後半部分(チェーンコード)を合わせて、子の拡張公開鍵(M/0)の完成です。

④子の子の拡張公開鍵を生成する

あとは、子の拡張公開鍵を生成するのと同じ手順でM/1を作ったり、M/0/0を作ったりして木構造を作っていけます。

さらなるセキュリティ向上のために(ハードニングされた秘密鍵の生成)

拡張公開鍵を活用すれば、拡張公開鍵をサーバに置くことでユーザー用のアドレスを自動でつくっていけます。秘密鍵をサーバに置く必要がないので、サーバから拡張公開鍵が盗まれたとしてもそれだけでお金を盗むことはできません。

しかし、サーバ上の拡張公開鍵(M/0)が盗まれ、さらに何らかの方法で、あるユーザの秘密鍵(m/0/0)が盗まれてしまったら危険な状況になります。

M/0とm/0/0から、サーバに置かれている木構造のすべての秘密鍵が知られてしまうのです。なぜすべての秘密鍵が知られてしまうのかを考えてみましょう。

ポイントとなるのは子の拡張秘密鍵(m/0/0)を生成する流れです。その流れは以下の通りでした。

今回の状況では、悪意のある者はM/0とm/0/0(下図の赤枠)を知っています。そのため、m/0(下図の青枠)算出できる可能性があります。

悪意のある者は、HMAC-SHA-512に入力する鍵が「0」であることは知りません。しかし、あてずっぽうに鍵に数値を入れていればいずれわかってしまいます。

そうして親秘密鍵のm/0がばれてしまったら、サーバ内の木構造の秘密鍵は簡単に算出されます。悪意のある者が手始めにm/0/1を算出することにした場合、以下のように計算します。


サービス運営者がすぐに気づけばまだよいですが、気づくのが遅れればユーザのアドレスからすべて資金が抜かれてしまい、大変な騒ぎになりそうです。

取引所のハッキングは上記のような感じで起こっているのかもしれないですね。秘密鍵がどのような経路で知られてしまうかは不明ですが、ちょっと怖い感じがします。ほとんどの取引所が「コールドウォレットでの管理で安全」とか言ってますが、いくらユーザー用アドレスの秘密鍵がオフラインで管理されていても、その親に当たる公開鍵がサーバ上に置かれていて、さらに何らかの方法でユーザー用アドレスの秘密鍵が1つでもわかれば、自分のお金を盗まれてしまうということなんですかね、、。

さらに悪いシナリオも存在します。それが起こるのは、悪意のある者がM/0とm/0/0に加えて、マスター公開鍵(M)も知っていたときです。

この場合、悪意のある者はマスター秘密鍵(m/0)を計算できます。悪意のある者はM/0とm/0/0から、m/0を求めることができています。そのため、m/0を算出する流れの中のMとm/0(下図の赤枠)を知っているということになり、マスター秘密鍵であるm(下図の青枠)を算出できてしまいます。


こうなれば、そのマスター秘密鍵(m)から派生するすべての秘密鍵が計算できてしまいます。

ハードニングされた秘密鍵の生成

サーバ上の拡張公開鍵(M/0)が盗まれ、さらに何らかの方法で、あるユーザの秘密鍵(m/0/0)が盗まれてしまったら、M/0から派生するすべての秘密鍵が知られてしまいます。

詳解ビットコインを読む限りですが、上記の問題は解決されていません。そもそもm/0/0を盗まれないようにする対策が求められるという感じでしょうか。

ただし、マスター公開鍵が知られてしまった場合に、マスター秘密鍵まで計算されてしまうという事態は予防できます。それを可能にするのが、ハードニングされた秘密鍵の生成です。

ややこしそうな名前ですがやっていることは単純で、ハッシングする入力を変更しているだけです。HMAC-SHA-512の入力に拡張公開鍵を使うのではなく、拡張秘密鍵を使っています。

HMAC-SHA-512の鍵は「0'」、子拡張秘密鍵は「m/0'」となっています。ハードニングされた秘密鍵の生成では「’」を付ける習わしのようです。

この記事が気に入ったらサポートをしてみませんか?