【Bitcoin】ビットコインにおける4種のウォレットについて

ビットコインは各々によって作成されたウォレットと呼ばれる、単純なデータベースの中に秘密鍵を保存しています。

このデータベースはビットコインネットワークと完全に独立していて、各々のウォレットの中でビットコインアドレスの生成や管理ができるようになっています。
そしてウォレットによって秘密鍵の生成方法は異なるため、セキュリティの強度も変わってくるのです。

今回の記事ではそれぞれのウォレットの種類と特徴についてご説明していきます。


# 1．非決定性（ランダム）ウォレット
ビットコインが生まれて、一番最初に採用された形式がこの非決定性（ランダム）ウォレットと呼ばれるものです。
このタイプのウォレットは、ランダムに生成された秘密鍵をただ単に集めた非常にシンプルな構造となっています。

ウォレット起動時に100個のランダムな秘密鍵を生成し、鍵を全て使い終わった段階で必要に応じてまたランダムな秘密鍵を生成していくような形です。
※通常のウォレットアプリでは、セキュリティを固くするために受信用のビットコインアドレスを毎回変更しているため、複数のアドレスが必要となります。

この構造は非常にシンプルなのですが、ビットコインアドレスが全てランダムで生成されているため、頻繁にウォレットのバックアップを行わないと、万が一、秘密鍵を消失してしまったとき、コインを失ってしまうことが欠点となっています。


# 2．決定性ウォレット（Seededウォレット）
決定性ウォレットは`Seeded`ウォレットとも呼ばれ、1つの共通の「シード」値から一方向に暗号化することで秘密鍵を算出していくウォレットです。

シードとはランダムに生成される数値で、他の値と組み合わせて複数の秘密鍵を生成します。

決定性ウォレットでは、このシード値があれば生成された全ての鍵を復活させられるため、シードが生成された状態でバックアップを一度取得すれば全てのアドレスの復元が可能となります。

ウォレットの移行やバックアップが簡単にできるようになった一方で、シードが盗まれると、ウォレット内のコイン全ての権限を盗まれてしまうことにもなるので、シードの取り扱いは十分に注意しないといけません。


## ※ Mnemonic Code （ニーモニックコード）について
決定性ウォレットを生成する際にシードとして使った乱数を表現する単語の列を`Mnemonic Code`（ニーモニックコード）といいます。
<img width="200" alt="IMG_1037.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/178137/3150fe79-674c-e74f-7d84-90621a25660b.png">

ニーモニックコードは初期設定時に表示される12から24個の単語の列のことで、この単語の列はシード値を再生成する際に利用されます。
つまり決定性ウォレットでバックアップを取得する際は、このニーモニックコードさえ覚えておけばいいということになります。

ニーモニックコードは「英語・日本語・スペイン語・中国語(簡体字)・中国語(繁体字)・フランス語・イタリア語」から好きな言語を選択することが可能で、ランダムに生成された文字列と比較して非常に覚えやすいことが特徴です。

以下URLからランダムなニーモニックコードを生成することが可能ですので、ぜひ遊んでみてください。
→ https://iancoleman.io/bip39/
※ドラクエのふっかつのじゅもんを彷彿とさせるので、おもろいです。ｗ

このニーモニックコードの仕組みは [Bitcoin Improvement Proposals](https://github.com/bitcoin/bips) 39（通称 `BIP39`）で定義されたものとなります。


# 3．階層的決定ウォレット（HDウォレット）
決定性ウォレットの最も進んだ形がBIP32で定義されている、階層的決定ウォレット（通称 HDウォレット）です。
現在の標準ウォレットとして推奨されている形はこの形式となります。

階層的決定ウォレットは鍵の構造が以下のようなツリー型となっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178137/b1e35c95-fc55-aa4c-8208-193692526d09.png)

HDウォレットではビットコインアドレスの標準形式として、以下の形式が用いられます。（通称 HDパス）
`m: マスターキー / a': アカウント / c: 受け取り種別(0: 受け取り用, 1: お釣り用) / i: インデックス`

決定性ウォレットでは、このアカウント（a`）の部分が 0 で固定値となっていますが、階層的決定ウォレットでは複数の値を用いることが可能です。

例えば生成形式が`m/1/0/10`の場合、マスターキーから作られた2番目の鍵（アカウント）の11番目の鍵という意味に成ります。

この形式のメリットはアカウントの数字に意味を付加することで、以下のようにブランチ単位でアドレス管理ができるようになる点です。

```
（アカウントへの意味付けの例）

アカウント1 = A社からの入金用
アカウント2 = B社からの入金用
アカウント3 = C社からの入金用
etc...
```

また、マスターキーも公開鍵暗号になっているため、マスターキーの公開鍵さえ所持していれば、受け取り用のビットコインアドレスを生成することができる点も大きなメリットとなります。
※この公開鍵は別名、拡張公開鍵と呼ばれます。


## ※ 拡張公開鍵の脆弱性について
拡張公開鍵から公開鍵を生成できることは非常に便利なのですが、この値には「チェーンコード」という値が含まれており、仮に1つでもビットコインアドレスの秘密鍵が流出してしまうと、チェーンコードを用いて同じブランチの秘密鍵を全て算出されてしまうという脆弱性があります。

この脆弱性への対策として、階層的決定ウォレットでは強化導出（`hardened derivation`）と呼ばれる導出関数を利用しています。
この関数は拡張公開鍵の代わりにマスターキーの秘密鍵を使ってチェーンコードを算出します。
そのため仮に1つのチェーンコードが流出したとしても、マスターキーの秘密鍵を知らない限りは他の秘密鍵を算出できなくなります。

この強化導出関数を利用するためには、ビットコインアドレス発行時の`HDパス`の各数値にアポストロフィを付与します。
`m: マスターキー / a': アカウント / c': 受け取り種別（0: 受け取り用, 1: お釣り用） / i': インデックス`

## ※ 受け取り種別とは？
`BIP32`でビットコインアドレスを生成する際の`c: 受け取り種別(0: 受け取り用, 1: お釣り用)`の意味について、ビットコインにおけるトランザクションの使われ方を踏まえて補足説明をします。

ビットコインが送金されるときトランザクションは以下の図のような流れとなっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178137/95d558b3-7fe4-9ad6-b5f0-d708a3638f14.png)

ビットコインの送金時には、今まで受け取ったトランザクションを用いて残高の算出を行い、そのトランザクションを用いて送金を行います。

今まで受け取ったトランザクションから、まだ未使用なトランザクション（通称: UTXO）を見つけ出し、その受け取ったトランザクションを用いて、送金のトランザクションを発行します。

受け取ったトランザクションの着金額と、送金しようとしている金額は合わないことがほとんどなので、その場合は差額のお釣りを自分に送金するような仕様になっています。

この時、発生するお釣りを受け取るためのビットコインアドレスなのか、それとも純粋にコインを受け取るためのビットコインアドレスなのかを判別するための`c: 受け取り種別(0: 受け取り用, 1: お釣り用)`となります。

# 4．最新のウォレット標準形式 BIP44
`BIP32`の規格に従いつつ、新しい標準形式として提案されているものが`BIP44`です。
※`BIP32`という大きな規格の中に`BIP44`が存在しているイメージです。

`BIP32`のツリー構造は非常に大きな柔軟性を持っている反面、子、孫、ひ孫…とほぼ無限にツリーを作成することができるので、ウォレット移行を行う際などに全てを辿ることができません。

そのため`BIP44`ではツリーの1階層目は1つだけのブランチを持つこととし、必ず強化公開鍵を用いて導出されるような規格となっています。
また、コイン種別の切り替えも可能とし、ビットコインだけでなく様々なコインのアドレスを発行することができるようになりました。

形式は以下のような形となります。
`m: マスターキー / p': 目的(44) / ct': コイン種別 / a': アカウント / c': 受け取り種別(0: 受け取り用, 1: お釣り用) / i': インデックス`

最初の`p'`には必ず「44」が入り、`ct`は暗号通貨の種類を示します。(ビットコインの場合、「0」となります)
それ以外の値については`BIP32`と同じものになります。

詳しく知りたい方は以下URLの`BIP44`のWikiもご覧ください。
→ https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki


# 5．おわりに
ビットコインアドレスの生成方法やウォレットの種類についてご紹介してきましたが、いかがでしたでしょうか。

実際に触ってみたい！という方は`bitcore-lib`というライブラリが使いやすいのでこちらを使って遊んでみるのがいいと思います。
→ https://github.com/bitpay/bitcore-lib

`bitcore-lib`については他の記事でもっと深く触れていきたいと思います。


# 参考文献
- [ビットコインウォレットのパスフレーズの互換性の話（簡単なHDウォレットの仕組み）](http://www.jpbitcoinblog.info/entry/20160522/1463905035)
- [ビットコインアドレスを自分の手で作って理解する](https://qiita.com/quincedaddy/items/2e54f35683facb519446)
- [マルチシグの仕組み（P2SH方式）](https://qiita.com/you21979@github/items/795236fde38d510bbdd1)
- [BIP16 Wiki](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)
- [BIP38 Wiki](https://github.com/bitcoinjs/bip38)
- [BIP44 Wiki](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
- [ビットコインとブロックチェーン:暗号通貨を支える技術](http://amzn.asia/fOPoyPb)