Gunosy Blockchain Blog

Gunosyの開発メンバーが知見を共有するブログです。

【ビットコイン】ウォレットの概要とHDウォレットの仕組み

このブログについて

データ分析ブログテックブログ のスピンオフとして今回ブロックチェーンブログを作りました。

本ブログでは社内の研究開発の一環として調査しているブロックチェーン技術に関連したコンテンツを書いていきます。

はじめに

こんにちは、 開発本部の @yamarkz です。

この記事は Gunosy Advent Calendar 15日目の記事です。(少し投稿が遅れてしまいました、すみません。)

昨日は @hoshitocat さんの Headless ChromeをDocker上で動かして、E2Eのテスト でした。

また、ブロックチェーン Advent Calendar で @mosa_siru さんが 仮想通貨マイニングに関するまとめ を書いてくれました。

今回はビットコインのウォレットの概要と仕組みについて紹介します。

ウォレットのイメージが湧かない方は先に (おまけ) として紹介した 様々なウォレット を見てみてください。

この記事のレベル感としては初級~中級の間をイメージして書いたので、既に知ってる内容ならガンガン読み飛ばしちゃってください。

f:id:yamarkz:20171214213305p:plain:w300

※ 文中ではわかりやすさを取るため仮想通貨という表現に統一させてもらいます。

※ 今回は入門者を意識した書き方になっており、例え話などが本来の仕組みとは少しズレた内容になっている部分もありますがご了承ください。

秘密鍵と公開鍵、ビットコインアドレス

ウォレットの仕組みの話に進む前に、前提知識として必要な「秘密鍵」「公開鍵」「ビットコインアドレス」について少し触れておきます。

ビットコインでは様々な部分で暗号化技術が用いられています。その暗号化技術の1つが「秘密鍵」と「公開鍵」です。

秘密、公開と言われてもイメージしにくいかと思いますが、秘密鍵は自分だけが知っている鍵のことで、公開鍵は全世界の人が知ることができる鍵のこと。

2つの鍵の仕組みは「公開鍵で文章を暗号化して、秘密鍵で暗号化された文章を解読する」といった感じです。自分しか秘密鍵は知らないので自分だけが文章を解読して読むことができます。

ビットコインの世界ではこの2つの鍵とビットコインアドレスを用いてビットコインの送金が行われています。

ビットコインアドレスは公開鍵から生成される値で、実際に送金を行う際の宛先として利用されます。

実際のアドレス: 1PEfGuBeXwxWqxreSVc2Qy8ezX96YBs44K

また、これら3つの値には生成の順序があり 秘密鍵 => 公開鍵 => ビットコインアドレス の順序で生成されます。

なので 鍵の所有主 = ビットコインアドレスの宛先主 と同義になります。

f:id:yamarkz:20171220085733p:plain:w400

今回はアドレス生成過程には触れませんが、上記の順序は送金の仕組みを理解する上で重要なプロセスなのでぜひ覚えてください。

送金のイメージを掴んでもらうために銀行ATMを例にしてみます。(※実際の送金は銀行ATMのように行われていません)

秘密鍵がお金を引き出す際に必要になる暗証番号で、公開鍵から生成されたビットコインアドレスが自身の口座番号に当たる部分になります。

送金者に自身の口座番号 (ビットコインアドレス) を教えて、お金を入金 (送金) してもらいます。

出金者は教えた自身の口座番号 (ビットコインアドレス) に入金されたお金を、自身が持つ暗証番号 (秘密鍵) を元に口座の所有権を証明し、お金を取り出します (使用します)。

このように口座番号 (ビットコインアドレス) 宛にお金を入金してもらい、暗証番号 (秘密鍵) を用いて取引を行います。

f:id:yamarkz:20171218174813p:plain:w300

ざっくりとした説明でしたが、まとめると。

  • ビットコインの送金のやりとりには暗号化技術である「秘密鍵」と「公開鍵」が用いられている
  • ビットコインでは「ビットコインアドレス」が送金時の宛先になる
  • 秘密鍵 => 公開鍵 => ビットコインアドレス の順序で生成される

それでは鍵の知識を踏まえてウォレットについて見ていきましょう。

ビットコインのウォレット

ビットコインの世界にはウォレット (財布) というものが存在します。

「ウォレット」という名前からはビットコインを保存しておくストレージなどを連想してしまいますが、ウォレットは 「鍵」 を保持し管理します。 ここでの鍵とは先ほど紹介した「秘密鍵」と「公開鍵」 のことです。

ビットコインアドレスは鍵から作られ、このアドレス宛に送金されることは先ほど紹介しました。

では、ビットコインを使用する時はどうするのでしょうか?

答えは、受け取ったビットコインに秘密鍵 (の署名) を用いて「このビットコインは自分の物である!」と証明を行い、この証明が成立することで初めて自分が次の用途に使うことができるようになります。

受け取りに必要になるビットコインアドレスは鍵から作られる。受け取ったビットコインを使う時に必要になるのは秘密鍵の署名による証明。

つまり、やりとりで必要なのは鍵であり、この鍵だけを管理すれば良いのです。

なので、ウォレットで鍵を所有すること = 鍵に紐づいたビットコインを所有すること になるのです。

f:id:yamarkz:20171215183221p:plain:w300

<鍵束のイメージ>

ウォレットは鍵の管理手法を軸に大きく分けて2種類に分類されます。

1つ目が 「ランダムウォレット」 、2つ目が 「HDウォレット」 です。

ランダムウォレットはビットコインが開発された初期の頃に用いられていたウォレットで、HDウォレットは後発で開発されました。

現在はHDウォレットの仕組みが主流となっています。

次にこの2つの特徴と仕組みを見ていきます。

(余談ですが、通貨取引所に預けるよりも自身のウォレットを持って管理することをオススメします。多くの人が取引所で通貨の売買を行なっていますが、取引所は常にGOX (悪意のあるユーザによる攻撃を受け通貨を喪失、紛失すること) される危険性があるからです。 今日もウクライナの仮想通貨取引所 「liqui」でBTCが盗まれたという情報を目にしました。自分の通貨は自分の管理下に置くことが一番安全ですね)

ランダムウォレット (非決定性ウォレット) とは?

非決定性ウォレット (以下、ランダムウォレット)とは、秘密鍵と公開鍵を1:1の関係で生成し管理するウォレットのことです。

ランダムウォレットはビットコインの初期に用いられていました。

仕組みは至ってシンプルで、ランダムウォレットを用いるクライアントでは初期起動時にランダムな秘密鍵を100個生成します。 *1

f:id:yamarkz:20171214212120p:plain:w400

<ランダムウォレットのイメージ>

この生成した100個の秘密鍵から公開鍵を1:1で生成し、さらに公開鍵からビットコインアドレスを生成して初めて利用できるようになります。

つまり、既にこの時点で100個の鍵の管理責任を負わなければいけない状況になるのです。これはなかなか大変ですね

「100個も鍵を作らずに1つの鍵を使い回せば良いのでは。。。。?」

と、思うかもしれませんが。基本的に個々の鍵はプライバシーの関係上、1度しか使われません。 これは鍵から生成されるアドレスから特定の個人が所有しているビットコインの額が割り出されることを防ぐためです。

(余談ですが、ビットコインでは特定のアドレスにいくら入っているのかを簡単に確認することができます。ここ の「サーチ」でアドレスを検索してみると... ?)

初期生成した100個を使いきった場合、さらに多くの秘密鍵を生成し管理しなければいけません。 こうなると保持する鍵の数が200...300と膨れ上がり管理コストが膨大になります。

さらに、鍵を紛失した場合にはその鍵に結びついていたビットコインは全て凍結する (誰も取り出せなくなる) ことになります。 この凍結を防ぐためにも、所有者は都度秘密鍵のバックアップを取る作業が必要になります。

このようにランダムウォレットは構造がシンプルではありますが、実際に使用するという点で見るとあまり使い勝手が良いとは言えません。

簡略まとめ

  • ランダムウォレットは構造がシンプル。秘密鍵:公開鍵が1:1の関係でできている
  • 構造がシンプルが故に複数の秘密鍵を保持、管理しなければいけない状況が作られる

次は、このランダムウォレットが抱える問題を階層構造によって解決したHDウォレットを紹介します。

Hierarchy Deterministicウォレット (階層的決定性ウォレット) とは?

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

HDウォレットの全てはシードと呼ばれる数値から始まります。

シード例: 381e5fb888a599b44b9341b2cdb8d08d13bf7333187be6ee3ab5fd63e9d22159d0980f8e80dfbba3ead7dd646634cd46a8984a6d2ee71c7f28eb5b885b0fa029

このシードを起点に暗号学的ハッシュ関数を用いて鍵を生成していきます。 シードから生まれた鍵を親鍵とすると。親鍵が子鍵を、子鍵が孫鍵を。というような順番で階層的に鍵を生成することができます。

親鍵、子鍵と言われてもパッとイメージしにくいと思うので下記のイメージを参考にしてみてください。

f:id:yamarkz:20171214212617p:plain:w400

<HDウォレットのイメージ>

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

この鍵の生成過程はBIP *2 で定義されているものが使われているため、シードがあれば何度でもHDウォレットを再構築することが可能です。

階層構造の仕組みにより管理すべき対象が1つのシードに絞られるため、ランダムウォレットのように秘密鍵を複数保持して管理する責任から解放されます。

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

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

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

簡略まとめ

  • シードと呼ばれる数値から鍵を階層構造に生成する
  • シードがあれば何度でもHDウォレットを再構築することが可能
  • 注力して管理するべき対象が「シード」のみに絞られるため管理コストを大きく下げることができる
  • シードが他人に知られた場合、そこに結びついていたビットコインを全て失うリスクが存在する

次にHDウォレットの仕組みで、最も重要な鍵生成過程を見ていきたいと思います。

HDウォレットの鍵はどのようにしてつくられるのか

先ほども紹介した通り、HDウォレットの全ては「シード」から始まります。 そしてシードがあれば何度でもHDウォレットの鍵階層を再構築することが可能です。

まずは鍵生成のイメージを掴んでもらいたいので下記の図を見てください。 下記の図はシードとマスター秘密鍵 (1番最初に生成される秘密鍵)の生成過程です

f:id:yamarkz:20171218162704p:plain:w400

<HDウォレットの鍵生成過程>

ぱっと見ただけではよくわからないですよね。

1つ1つ見ていくと。

  1. 暗号学的に安全な乱数生成器でシード (数値)を作成
  2. HMAC-SHA512 (一方向性ハッシュ関数) に乱数をかける
  3. 関数から512ビットの値が生成される。これを256ビットずつ前半と後半に分ける
  4. 前半部分 (left) を「秘密鍵」後半部分 (right) を「ChainCode」とする
  5. ChainCodeは子秘密鍵の生成に用いる

ここまでで、乱数生成器から「シード」が生成され、HMAC-SHA512から「秘密鍵」と「ChainCode」が生成されました。

f:id:yamarkz:20171218171124p:plain:w400

<実際に生成したSHA512の値>

ここから、「秘密鍵」「ChainCode」「index」を用いて階層鍵を作成していきます。

「ChainCode」とは、シードのことで子鍵生成のために用いられる値です。

「index」とは、生成される子鍵を識別する値です。0なら第1子、1なら第2子、2なら第3子というように子供の識別子として用いられます。

f:id:yamarkz:20171218143237p:plain:w400

<HDウォレットの子鍵生成過程>

  1. 「秘密鍵」「ChainCode」「index」を用意する
  2. 上記3つの値を左から順に組み合わせる。組み合わせた値をHMAC-SHA512 (一方向性ハッシュ関数) にかける
  3. 関数から512ビットの値が生成される。これを256ビットずつ前半と後半に分ける
  4. 前半部分 を「秘密鍵」後半部分 を「ChainCode」とする
  5. ChainCodeは子秘密鍵の生成に用いる

あとは上記の1~5の過程を何度も繰り返せば階層的に無限に鍵が作れます。

さらに、過程で生成された秘密鍵からは公開鍵が生成でき、公開鍵からはビットコインアドレスが作られ送金に利用されます。

上記を端的に話すと、

「秘密鍵」「ChainCode」「インデックス値」を組み合わせることで無数に鍵が生成することができるということです。

以上が鍵の生成フローです。

パスフレーズとBIP32とBIP44

最後にHDウォレットのパスフレーズ、そしてBIP32とBIP44を見ていきます。

f:id:yamarkz:20171214212835p:plain:w400

<HDウォレットの鍵階層のイメージ>

https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki

HDウォレットで階層的に鍵を管理すると何かと良いことのはわかりました。 では、特定の階層に存在する特定の鍵を指定したい場合どのように鍵を一意に特定するのでしょうか?

答えは、「パスフレーズ」と呼ばれるフォーマットを鍵に適用し管理します。

パスフレーズとは、どの階層にどの鍵が存在するのかを一意に表したもので階層をスラッシュ ( / ) 区切りで表現します。

例: m/2/0/3

上記は、マスター鍵(m) から作られた 3番目の個鍵(2) から作られた1番目の個鍵(0) から作られた4番目の個鍵(3) という意味です。

BIP32ではこのパスフレーズに標準的な意味づけを定義しています。

BIP32の標準規格: m/a'/c/i

上記では、マスター鍵 (m) から作られた アカウント番号 (a') から作られた 用途が受け取りかおつりかの識別子 (c) から作られた秘密鍵を元に使いまわすビットコインアドレス部分 (i) という意味です。

このパスフレーズとBIP32の標準規格を用いて構造を形式化し管理しています。

これらを踏まえ、BIP32の標準規格を踏襲し、新たに階層を形式化を行い定義したものがBIP44です。

BIP44の標準規格: m / purpose' / coin_type' / account' / change / address_index

各階層ごとの意味を分解してみると下記の様になります。

  • (m) マスター鍵
  • (purpose') 目的階層。 44に設定された定数
  • (coin_type') コインの種類階層。Bitcoinは0 / Bitcoin Testnetは1
  • (account') 使用目的階層。寄付目的 / 貯蓄目的 / 共通経費 など使用するユーザー側で決めることができる
  • (change) 受取階層。外部送金者からの受け取りが0 / 自身のトランザクションからのおつりの受け取りが1
  • (address_index) アドレス階層。インデックス値が振られる

この様にBIP32よりも多くの階層を設けて鍵を管理するのがBIP44です。 これらの具体的な内容は こちら で紹介されています。

簡略まとめ

  • HDウォレットの鍵はパスフレーズとBIPの標準規格で管理される
  • BIP32とBIP44は互換性がない。
  • BIP32を踏襲し、新たに規格を制定したのがBIP44

HDウォレットのメリットとデメリット

HDウォレットの仕組みの話を振り返り、メリットとデメリットを整理してみます。

メリット

  • 管理に注力すべき対象がシードのみに絞られるため管理が楽
  • ツリー構造になっていることで、「特定の鍵階層以下を特定の支払いにのみ使う」という使い方ができるようになる

デメリット

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

まとめ

今回の内容をまとめると

  • ビットコインの送金では暗号化技術が用いられている。「秘密鍵」「公開鍵」
  • 「秘密鍵」=> 「公開鍵」 => 「ビットコインアドレス」の順で生成でき、ビットコインアドレスは送金の宛先になる
  • ビットコインのウォレットとは鍵束のこと
  • ウォレットは管理手法を元に分けると2種類ある 「ランダムウォレット」と「HDウォレット」
  • ランダムウォレットは 秘密鍵と公開鍵を1:1で生成し管理する。鍵の数が増え続けて管理コストが大きくなる問題がある
  • HDウォレットは階層的に鍵を生成し、ランダムウォレットが抱える管理課題を解決する
  • HDウォレットの鍵の生成過程には暗号学的計算が用いられている
  • 「秘密鍵」「ChainCode」「index」を用いて階層鍵は生成される
  • 階層上に存在する鍵の位置は「パスフレーズ」を用いて特定する
  • パスフレーズに意味を持たせて鍵を管理する仕組みを取っている
  • BIP32で定義したパスフレーズの拡張として新たに階層の意味を定義したのがBIP44
  • BIP32のパス構造とBIP44のパス構造には互換性がない

これらの内容に関連した BIP一覧

様々なウォレット (おまけ)

様々なウォレットを紹介します。 ウォレットには web/アプリ/ハードウェア と様々なタイプが存在していますが、今回はその中でも特徴のあるウォレットをいくつかピックアップしました。

Bitcoin Core (公式)

Bitcoinの公式クライアントです。このクライアントでは実際にブロックチェーンを構築するため、初期同期時には65GB以上のデータをネットワーク上からダウンロードします。なので起動には多くの時間を要するため 我慢が必要です。 必要な容量は同期時間などを考えると、カジュアルな支払いに利用することには向いてませんね。

f:id:yamarkz:20171219184750p:plain:w300

ダウンロード - ビットコイン

bread (アプリ)

breadはiOS, Androidのウォレットアプリです。 最近ICOも行われていました。https://token.breadapp.com/jp/

f:id:yamarkz:20171219185209p:plain:w300

bread

Copay (アプリ)

Copayはマルチシグネチャと呼ばれる技術を用いたウォレット。コペイという呼び名が僕は好きです

iOS, Androidをはじめ、様々なデバイスで動きます。また、オープンソースとしてソースコードが公開されているのも特徴です。

f:id:yamarkz:20171218160634p:plain:w300

Copay – 安全な共有ビットコインウォレット

Trazor (ハードウェア)

ハードウェアのウォレット、Trazor (トレザー)。

Trazorは界隈で最も信頼の置けるウォレットとして人気です。 バーチャルな通貨でも、最終的には実物で管理するのが一番安全だと言われています。(笑)

f:id:yamarkz:20171218160856p:plain:w300

TREZOR Bitcoin Wallet (Official) | The most secure hardware wallet.

最後に

長くなってしまいましたが、ウォレットの概要を掴むために主要なトピックを抜き出して紹介しました。ランダムウォレットからHDウォレットへの管理方法の進化を本記事で掴んでもらえたら嬉しいです。また、今回は内容の関係上触れることができていない技術や仕組みがたくさんあります。後日機会があればこれも紹介したいと思います。

宣伝

Gunosyでは、blockchain.tokyo を主催するなど、ブロックチェーンや仮想通貨に関する調査を行っています。

次回は来月、メルカリさんに会場をお借りしてイベントを開催する予定ですので、興味がある方はぜひ下記のイベントページからのご参加お待ちしております。

blockchain-tokyo.connpass.com

また、弊社ではブロックチェーンを始めとしてやスマートスピーカー、VR/ARと言った新規領域での研究・開発を進めており、メンバーを募集しています。

www.wantedly.com

*1:ビットコインコアクライアントでの話

*2: BIPとは (Bitcoin Improvement Proposal) のこと、直訳すると「ビットコイン改善案」。改善案という表現がされていますが、BIPではビットコインの仕様を定義する場としても用いられています。bips