ビットコインの情報サイトの運営者ブログ

サイトには掲載していない仮想通貨に関する時事的な情報や個人的な感想など。中級者以上向け。

ビットコインウォレットのパスフレーズの互換性の話(簡単なHDウォレットの仕組み)

普段あまり使っていないので気が付きませんでしたが、最近Blockchain.infoがリニューアルしてHDウォレットになったようです。新しいウォレットでは、複数のアドレスを簡単に使い分けられるようになり、バックアップも1回とっておくだけで良くなりました。

恐らく誰もが一度は気になることだと思いますが、実はバックアップ用のパスフレーズは異なるウォレットソフト間で互換性があまりありません。例えばBlockchain.infoのパスフレーズをモバイルウォレットのBreadwalletやデスクトップウォレットのElectrumで使うことはできません。Blockchain.infoのHDウォレットはBIP44という方法を元に作成されており、BreadwalletやElectrumはBIP44に未対応なためです。

Blockchain.infoと互換性があるのはデスクトップウォレットのMultibit HDやモバイルウォレットのMyceliumなどです。

この原理を理解するにはHDウォレットの仕組みをある程度知る必要があります。

HDウォレットとは?

HDウォレットとは、Hierarchy Deterministicウォレットの略で階層的決定性ウォレットなどと訳されます。通常、ビットコインアドレスに対応する秘密鍵は固有のものが一つあり、新しいアドレスを作成するたびにバックアップを新しくとらなければなりません。HDウォレットは、一つのseed(種)から無限に近いアドレス/秘密鍵のペアを作成できるウォレットのことで、seedさえメモしておけば追加にバックアップすることなく簡単にいくらでもアドレスを使い分けることが可能です。

同じアドレスを使いまわしている人は多いと思いますが、セキュリティ上やプライバシー保護の観点からあまり推奨はされていません。HDウォレットでは受取毎・送信毎にビットコインアドレスを変更する、というのが基本設計でありバックアップの利便性を保ちながら同時にセキュリティやプライバシーを保護できます。また、秘密鍵に触れることなく「マスター公開鍵」からビットコインアドレスを生成できるという仕様があるため、例えばサーバー上に秘密鍵を保管することなく通販店のお客さん毎に安全にそれぞれの支払先アドレスを作成することも可能です。

HDウォレットではウォレット間の互換性を保つためにいくつかの規格が提案されています。

BIP39(パスフレーズ⇒seed)

bips/bip-0039 at master · bitcoin/bips · GitHub

先ほど触れた「seed」そのものは非常に覚えづらいため、覚えやすいようにいくつかの単語から構成された「パスフレーズ」からseedを作成しようという提案がBIP39です。

上のgithubのBIP39のページでは英語や日本語、中国語などの様々な言語の単語が規定されています。このように単語リストを規定しておくことで、ウォレットソフトがみんなBIP39の単語リストを利用していれば互換性を保てるというわけです。実際にほとんど大部分のウォレットはBIP39に従っています。しかし注意しておきたいのが、この単語リストには複数の言語があるということです。英語のパスフレーズはすべてのウォレットが導入していますが、例えば日本語のパスフレーズに未対応のウォレットも多くあります。このせいで、一部のウォレット間で互換性がないという状況が生まれてしまっています。例えば、モバイルウォレットのbreadwalletは日本語のパスフレーズを生成しますが、デスクトップウォレットのMultibit HDは英語にしか対応していないので、英語ユーザーはbreadwallet⇒Multibit HDのパスフレーズのインポートができるが、日本語ユーザーはできないという状況になっています。

BIP32(HDウォレットの基本規格)

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

HDウォレットの基本的な規格を定めたのがBIP32です。デスクトップウォレットのElectrumを除くほとんどすべての主要ウォレットはこのBIP32に従っています。

f:id:jpbitcoin:20160522152234p:plain

BIP32のウォレット構造は上の画像のとおりです。まず、(パスフレーズ⇒)seedからマスターキー(Master Node)を作成します。この一番上の階層のマスターキーは通常m(M)で表します。マスターキーにはマスター秘密鍵とマスター公開鍵があり、マスター公開鍵をウォレットソフトにインポートすることによって、秘密鍵に触れることなくアドレスを新規作成できる閲覧専用のウォレットを管理することが可能です。

HDウォレットのフォーマット(HD path)

マスターキーからほとんど無限に近い数のアドレス/秘密鍵のペアを階層的に作成することが可能です。階層構造の中のアドレス/秘密鍵の位置を示すフォーマット(path)も規定されています。

フォーマットはm/5/0/3のようなかたちであらわします。階層はスラッシュで区切り、m/5/0/3であれば、マスター秘密鍵(m)から作られた6番目の子鍵(m/5)の1番目の子鍵(m/5/0)の4番目の鍵(m/5/0/3)ということになります。

先ほどの画像では、一番右下の鍵はm/i/l/kと表現されています。マスター秘密鍵(m)から作られたi+1番目の子供(m/i)のl+1番目の子供(m/i/l)のk+1番目の鍵(m/i/l/k)ということです。

このように階層的にウォレットを作成することで、用途別に分類して鍵を作成していくことができます。例えば複数アカウントを管理できるウォレットでは、一番目のアカウントのマスターキーはm/0、二番目のアカウントのマスターキーはm/1を使うようにします。さらに下の階層で受け取り用のアドレスとお釣り用のアドレスを分けます。1番目を受け取り用、2番目をお釣り用のマスターキーとすれば、それぞれm/0/0、m/1/0が受け取り用、m/0/1、m/1/1がお釣り用となります。実際に使うアドレスはさらに下の階層で順に作成していきます。受け取り用のアドレスは、m/0/0/0、m/0/0/1、m/0/0/2・・・、お釣り用のアドレスは、m/0/1/0、m/0/1/1、m/0/1/2・・・といった具合です。

一般にBIP32の標準形式はm/a'/c/iで表されます。a(account)がアカウント番号、c(change)がお釣り用(0=受け取り用、1=お釣り用)、iが通常使うアドレス/秘密鍵でiの数字を増やしてアドレスを新規作成します。単一アカウントしか管理できないウォレットではm/0'/c/iとなります。お釣り用のcの部分は、0のとき「external(外向き)」、1のとき「internal(内向き)」と呼ぶ場合もあります。受け取り用アドレスは外部に公開するため、お釣り用アドレスはソフト内部で利用するためということからきています。(aについているアポストロフィ'は次の項目で説明します。)

ただ単に「BIP32」と言ってもこの標準形式だけを指す場合と、HDウォレット全体の規格としてBIP32と言う場合があるのでご注意ください。

※お釣り用アドレスとは、ビットコインを相手に送信した後に残る「お釣り分」を送信する先の新しく作成するアドレスのことです。例えば1BTCを保有する自分のアドレスAから相手のアドレスBに0.8BTCを送る時、残りの0.2BTCは新しく作成した自分が管理するお釣り用アドレスCに送信することになります。通常HDウォレットではこのような作業を行っています。

hardened key(強化鍵)

最初のほうに書いたようにHDウォレットでは、秘密鍵を利用することなく親の公開鍵から子の公開鍵を作成することができ非常に便利です。しかし、実はこの「マスター公開鍵」には公開鍵以外にもチェーンコードと呼ばれる別の情報も含まれており、もし子の秘密鍵が流出してしまうと、子の秘密鍵と親のマスター公開鍵内のチェーンコードを利用して、その他の子の秘密鍵が全て判明してしまうという脆弱性があります。

セキュリティを強化するためにマスター公開鍵から子の公開鍵(アドレス)を生成できなくし、秘密鍵からのみアドレスを生成できるようにしたのがhardened keyと呼ばれるものです。

hardend keyは数字の右上にアポストロフィ(')をつけてm/0'/0'のようなかたちであらわします。

BIP44

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

BIP32に従いつつ新しい標準形式として提案されているのがBIP44です。BIP32の標準形式(m/a'/c/i)とは異なるので、「BIP32ではなく」BIP44という書かれ方をされることもありますが、基本的にはBIP32という大きなHDウォレット規格の中の一つがBIP44であるというイメージです。

BIP44は一部のウォレットしか導入していないため、BIP44を導入していないウォレット間の互換性がないという状況が生まれています。

BIP44の形式は

m / purpose' / coin_type' / account' / change / address_index

と規定されています。通常のビットコインウォレットの場合は、m/44'/0'/a'/c/iというかたちになります。各階層についてひとつひとつ見ていきましょう。

purpose

目的を表す階層です。BIP44のHDウォレットではBIP「44」の部分をとって、45番目の鍵(44')が使われます。

coin_type

コインの種類です。ビットコインは「0」であり、ライトコインは「2」と規定されています。この階層を導入することにより、複数の仮想通貨を管理しながらバックアップは一つのパスフレーズだけで済むという非常に便利なウォレットを実装することが可能です。現状この階層をまともに利用しているのは複数通貨をサポートしているAndroid用のモバイルウォレットCoinomiぐらいで、普通のビットコインウォレットは「0」しか使っていません。

slips/slip-0044.md at master · satoshilabs/slips · GitHub

BIPではありませんが、どのコインがどの番号かというのは上のリンク先で提案されています。

account' / change / address_index

残りはBIP32の標準形式と同じです。単一のアカウントしかサポートしていないウォレットではこの部分は0'/c/iとなります。つまり全体としてはm/44'/0'/0'/c/iとなります。

gap limit(lookahead)

HDウォレットのパスフレーズの互換性を考えるうえで最後に重要なものがgap limitです。

例えばBIP44のウォレットの場合、m/44'/0'/0'/0/0、m/44'/0'/0'/0/1、m/44'/0'/0'/0/2、m/44'/0'/0'/0/3・・・と順に受取用アドレスを生成していきますが、もしウォレットを紛失してパスフレーズから復元する場合、最後にどのアドレスを生成したのか?ということは分かりません。そこでウォレットソフトでは1番目から順番にアドレスを生成して使用済のアドレスかどうかチェックします。gap limitの数だけ未使用のアドレスを発見すればそこで生成を止めます。

BIP44の標準のgap limitは20とされています。つまり20のアドレスが連続して未使用であればアドレスのチェックを止めるということです。例えば、m/44'/0'/0'/0/0~m/44'/0'/0'/0/10までが使用済ということであれば、念のためm/44'/0'/0'/0/30まで使用済のアドレスがないかチェックします。

ウォレットソフトの中には自分でアドレスをどんどん新規作成できるものもあります。このようなウォレットの場合、もし100個のアドレスを新規作成した後、100番目のアドレスだけでビットコインを受け取ってしまうと、gap limitが100以上でないと、パスフレーズから復元してもビットコインが見つからないということになってしまいます。gap limitが少なすぎる不親切なウォレットの場合、正確にパスフレーズをバックアップしておいたはずなのにビットコインがない!なんて事件が起こる可能性もあります。このような場合はどんどんアドレスを新規作成していくことでビットコインが見つかります。

 結局ビットコインウォレットのパスフレーズの互換性はどうなの?

これまで見たようにひとくちにHDウォレットのパスフレーズといっても、BIP39の単語リストを使用しているか、各言語に対応しているか、複数アカウントに対応しているか、BIP44に対応しているか、gap limitが少なすぎないか、等々の互換性を失う要素が非常に多くあります。

基本的にはパスフレーズから復元するときは、同じウォレットソフトを使うというのが一番無難だと思います。しかし、全く互換性がないというわけでもないので、必要以上に恐れる必要もありません。iOSを紛失したからこれを機にAndroidに乗り換えたいけどbreadwalletにビットコインが・・・、という場合もなんとかなります。例えばマルチプラットフォーム(iOS/Android/Mac/Windows/Linuxなど)対応のウォレットであるCopayは、HDウォレットのフォーマット(path)を指定してパスフレーズをインポートすることも可能です。

新しいBlockchain.infoのHDウォレットも、これまで直接秘密鍵をバックアップしていた旧ウォレットに比べて不安になる方もいるかもしれませんが、BIP44に従っているので他のウォレットソフトへのインポートも可能です。

ちなみに、BIP39/BIP32/BIP44のおかげで、複数のウォレットソフトで同じパスフレーズを使いまわして同時利用する、といった利用法も可能ですが、セキュリティ上やめておくことをおすすめします。