少しだけ易しいMastering Bitcoin【第4章】

Bitcoinの技術面を学ぶにはこれしかないと言われているほどの名著Mastering Bitcoin を今更読んだので、自分の中での復習を兼ねて、ところどころ解説付きでまとめを書いていきます。


元の本ではサラッと流されているところもしっかり解説するつもりでお節介に書いたので初学者の人には分かりやすいかもしれません。


日本語版PDFはここで無料公開されているので翻訳者の方々への感謝を常に感じながら読みました。

無料公開版ということもあって誤字脱字もたまにあったりするので、

しっかり製本されたものが読みたいという方はAmazonで買って読むことをお勧めします。



前回はこちら↓


第4章 鍵、アドレス、ウォレット


⑴鍵について


Bitcoinの各ユーザーは「秘密鍵、公開鍵、 Bitcoinアドレス」の3つを持つことになります。

これら3つは「秘密鍵から不可逆関数(A→Bを求めるのは簡単だがB→Aを求めるのは難しい関数)を通して公開鍵が生成され、公開鍵を不可逆関数に通してBitcoinアドレスが生成される」という関係を持っています。


数学的な不可逆関数には素数のべき乗や楕円曲線上のスカラー倍算などがあるが、Bitcoinの鍵・アドレスでは楕円曲線上のスカラー倍算が使われています。


(a)秘密鍵

秘密鍵はランダムに選ばれる1から 2^256 までの間の数値です。

暗号学的に安定なランダムな数値から集められた任意の長さを持った文字列を取得し、256bitの数値を作るSHA256ハッシュアルゴリズムに放り込むことで暗号学的にランダムな値を生成します。

この秘密鍵の生成では、真に暗号学的に安全な擬似乱数生成器(CSPRNG) を使うことが重要です。


(b)公開鍵

公開鍵は、数学的な不可逆関数(ここでは楕円曲線状のスカラー倍算)に秘密鍵を通すことで求めます。


※ここで使われている楕円曲線暗号についてはこのページの解説が分かりやすいです


楕円曲線上のスカラー倍算を使った秘密鍵から公開鍵を生成するアルゴリズムを、以下の画像をイメージしながら死ぬほど簡単に説明すると、


①Bitcoinはこういう楕円曲線を使います!と決まっている

②Bitcoinは楕円曲線上の始点(ベースポイント:G)をここにします!と決まっている

③この始点における楕円曲線の接線を引いて、その接線と楕円曲線の交点とx軸対照の点を次の始点にします!(G, 2G, 4Gと2倍ずつ)というのを繰り返すルールを設定します!と決まっている(正確にはG, 2G, 3G...としていくのがスカラー倍算なのですが、なぜかグラフが2倍ずつになっていました)

④秘密鍵をインプットします!

⑤秘密鍵(乱数)の回数だけ③を繰り返します!

⑥その結果たどり着いた点を公開鍵とします!


という手順です。

(Bitcoinではsecp256k1(y^2 = x^3 + 7)という楕円曲線を使っており、各パラメータはここで確認できます)


この①~⑥の手順で秘密鍵から公開鍵を導出するのは簡単ですが、

「公開鍵(最終的に辿り着いた点)が始点(ベースポイント)から何回(秘密鍵)移動した点でしょうか?」と聞かれたら、簡単にはわかりませんよね。

解こうと思ったら1回の移動時はここになる、2回の移動時はここになる、って試していくしかなさそうです。

実はコンピュータにもそれと同じくらい地道な方法じゃないとわからないんですよ。

つまり、A→Bを求める速度とA←Bを求める速度に大きな差があることで、A,Bの数字を大きくすればするほどこの速度の差が開いていき、現実的に導出不可能になります。

なので不可逆関数なのです!


という感じですね。


つまり、公開鍵は楕円曲線上の点であるので

x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

という二次元座標(xとyのペア)で構成されます。



⑵Bitcoinアドレスについて

上の図のように公開鍵から SHA(Secure Hash Algolism)256やRIPEMD160(RACE Integrity Primitives Evaluation Message Digest)(ライプエムディー160と読む)などのハッシュ関数を通して公開鍵のハッシュ化をし、それをBase58Check Encodeという方式でエンコードして人間に読みやすい状態にしたのがBitcoinアドレスです。


このBase58Check encodeについて詳しく見て行きます。(今後も頻出するので重要な部分です)

まずBase58は、10進数の数を16進数で表すとより少ない行で書けるのと同じように、より多くの文字(58種類[アルファベット小文字26, 大文字26, 数字10から見間違えやすい数字の0, 大文字のo, 小文字のL, 大文字のi の4つを抜いたもの])で表して桁数を少なくするエンコードのことです。これによって人間による見間違いなどを防ぎます。


さらにBase58Checkは、以下の図のように行われます。

  • payloadがエンコードするデータ本体(公開鍵、秘密鍵など)です。
  • 最初に今回のエンコードでは何をエンコードするかというversionをprefix(接頭辞)としてつけます(Bitcoinアドレスの場合先頭はゼロ(16進数で0x00), 秘密鍵のエンコードなら128(16進数で0x80) )
  • 次にversion prefix + payload をSHA256に二回通したものの最初の4バイトを suffix(接尾辞)としてつけます(これをChecksumと言います)
  • 最後にBase 58でエンコードして(ex. Bitcoinアドレスが)完成です


このBase58Check Encodingをすることにより、


version prefix が以下の表のような対応でエンコード後の出力結果の頭にもつくので、その出力結果が「何をエンコードしたものなのか・どんな用途のものなのか」が一目でわかる

(ex. Base58Check Encodingしたものの先頭が1だったら、これはBitcoinアドレスだなと分かる)

checksumがあることによって打ち間違いなどを検知できる。

例えばBitcoinアドレスを送金のために入力した場合、そのBitcoinアドレスをBase 58 デコードしたもの(Dとする)の "versionとpayload部分" をSHA256に二回通したものが、Dの最後の4バイトと同じになれば、そのアドレスは全く関係ない適当な文字列ではなく、このBase58check Encodingで作られたもの(つまりBitcoinアドレスとして存在する)とチェックすることができる。


というメリットがあります。


<ここまでの僕の疑問点>

・なぜ秘密鍵から公開鍵を生成して、その公開鍵をそのままアドレスとして使わないのか? わざわざBitcoinアドレスを生成する必要は?

→ 

1. 単に複数回の暗号化によるセキュリティ向上のため

2. Base58 Encodingによって「その文字列が何を表しているのか分かりやすくなる」「打ち間違いを検知できる」ようにするため

2. 秘密鍵は「お金が動かせる」鍵、公開鍵は「bitcoinアドレス(銀行口座みたいなもの)を開設できる鍵」であり、"お金は動かせないけど口座は開設出来るという権利"を使用したいから



⑶公開鍵や秘密鍵の圧縮

ほとんどのトランザクションは、所有者の証明書を検証したりbitcoinを使うために、"公開鍵"を含んでいるため、公開鍵のサイズが圧縮されていない520bitの状態(プレフィックス(接頭辞) + X座標 + Y座標)だと、トランザクションが増えるにつれてBitcoinノードのディスクスペース(データ容量)が食われてしまってつらいです。


ここで公開鍵の構成について見直すと、公開鍵は楕円曲線上の点(x, y)であり、楕円曲線の方程式は決まっているので、xさえわかればyは簡単に導出できます。

つまり、公開鍵はprefix + xだけ に圧縮できる(50%くらい圧縮できる)のです。

ただ、楕円曲線は

のような形をしているため、x座標が決まってもy座標は +と -の両方が出てきてしまいます。


そこで、y座標が正の時にはprefixに 02をつけて「02 + X座標」を圧縮された公開鍵、y座標が負の時にはprefixに03をつけて「03 +X座標」を圧縮された公開鍵 としています。

一方で、圧縮されていない公開鍵は prefix 04 + X + Y として区別しています。(以下の画像参照)

しかし、ここで問題が発生してしまいます。

もちろん圧縮された公開鍵がデフォルトで使われるようになってきてはいるのですが、全てのBitcoinクライアントが圧縮された公開鍵を使っているわけではありません。

そして、圧縮されていない公開鍵と圧縮された公開鍵はもちろん違った数字列ですので、そこから生成されたBitcoinアドレスは異なるアドレスになってしまいます。


これによって「ウォレット(Bitcoinクライアント)の移行」の際に問題が生じるのです。

ウォレットは初めに秘密鍵を登録されると’それによって生成した公開鍵から生成されたBitcoinアドレス’を導出し、そのBitcoinアドレスのこれまでのトランザクションをブロックチェーンネットワークに探しに行って残高照会などをします。

この時、新しいウォレットは渡された秘密鍵から「圧縮されていない公開鍵→Bitcoinアドレス」を使ってトランザクションを探しに行けばいいのか、「圧縮された公開鍵→Bitcoinアドレス」を使ってトランザクションを探しに行けばいいのか判別できないのです。


この問題は以下のように解決されています。


もし以前使っていたウォレットが圧縮された公開鍵に対応したものだったら、そのウォレットから秘密鍵をエクスポート(出力)する時に、16進数秘密鍵の最後に01のサフィックスが付け加えられてWIF(wallet import format)形式で出力された結果、Kや Lから始まる秘密鍵がエクスポートされます。

もし以前使っていたウォレットが圧縮された公開鍵に対応していないものだったら、そのウォレットから秘密鍵をエクスポートする時に、16進数秘密鍵がそのままWIF形式で出力され、5から始まる秘密鍵がエクスポートされます。


その5 or K, Lの違いによって、エクスポートされた以前のウォレットの秘密鍵をインポートされた新しいウォレットは、以前のウォレットが使っていたBitcoinアドレスが圧縮された公開鍵から生成されたものだったのか圧縮されていない公開鍵から生成されたものだったのかを判断することができ、適切にこれまでのトランザクションを探しに行くことができるようになっているのです。

⑷ウォレット

前提としてウォレットは”鍵”(秘密鍵と公開鍵)を持っているだけで、bitcoinを持っているわけではありません。ウォレットというよりキーホルダーですね。


その鍵を用いて、これまでのブロックチェーンにあるトランザクションに署名をすることによって、その自分へのアウトプットトランザクションのロックを解除してそのアウトプット分のBitcoinが自分のものだと証明するのでした。


①ウォレットの種類とその仕組み

実は、1つのウォレットが持っている秘密鍵・公開鍵・Bitcoinアドレスは一つではなく、めちゃめちゃたくさんあります


これは、プライバシーを守るためです。もしあなたのウォレットが使うBitcoinアドレスが唯一であったらBitcoinブロックチェーンネットワークのあなたのBitcoinアドレスを探索すれば「'そのBitcoinアドレス=ウォレット'が今いくらのBitcoinを持っているか」が分かってしまいますよね。

(実際にはウォレットがいくらのBitcoinを所持しているか分かったとしても、それが誰のものかは分かりませんが、多額のBitcoinを所持していたりする場合は「この時間にこれだけの額のBitcoinを送金しているのは〇〇しかいない」と現実世界の個人が特定されてしまうこともあります)


これを防ぐために、大半のウォレットはトランザクションの度に秘密鍵・公開鍵・Bitcoinアドレスのセットを生成するのです。

このことを前提にウォレットの種類を説明して行きます。


ウォレットの種類は大きく分けて2種類あります。


(a)ランダムウォレット

まず1つ目のウォレットが「非決定的ウォレット(ランダムウォレット)」です。"Just a Bunch Of Keys(ただのめっちゃめちゃ沢山の鍵)”またはJBOKというニックネーム がつけられています。笑

主にBitcoin初期に使われていたのがこのウォレットです。


このウォレットは初回起動時にランダムに100個の秘密鍵を生成します。もちろんその秘密鍵から公開鍵を生成し、Bitcoinアドレスを生成します。

そしてトランザクションの度にその中から一つずつアドレスを使い捨てて行きます。

トランザクションが多くなって足りなくなったら再び秘密鍵を100個生成して行くような仕組みです。


復習すると、秘密鍵を使って署名することによってその秘密鍵から生成された公開鍵から生成されたBitcoinアドレスに紐づいたアウトプットトランザクションの所有権が証明できるんでした。

なので、このランダムウォレットのようにたくさんの秘密鍵を1つのウォレットが持っていたら全部の秘密鍵を管理しなくちゃなりませんね。

これだと紙などのアナログな手段でバックアップするのは超絶大変になってしまいます。


(b)HDウォレット

そこで 考案されたのがもう1つのウォレットである「階層的決定性ウォレット(Hierarchy Deterministicウォレット:HDウォレット)」です。


HDウォレットはSeedと呼ばれる512bitの文字列(例:3338a6d2ee71c7f28eb5b882159634cd46a898463e9 d2d0980f8e80dfbba5b0fa0291e5fb88 8a599b44b93187be6ee3ab5fd3ead7dd646341b2cd b8d08d13bf7 )

から、実質無限に秘密鍵・公開鍵・Bitcoinアドレスの三点セットを生成することができるウォレットです。


以下の図のようにSeedからMaster keyを作り、そのマスターキーが親となってたくさんの子供(三点セット)を作り、またその子供が親になって子供をつくるという構造になっています。

無限に作られる秘密鍵の全てが唯一のSeedから生成されるので、利用者はこのSeedだけを覚えておけば良いことになります。

これでランダムウォレットの「秘密鍵めっちゃ覚えとかなきゃいかんやん問題」は解決されますね。


では、このHDウォレットがSeedから秘密鍵を生成していく仕組みについて解説して行きます。

まずはSeedからMaster keyの生成を見て行きます。

上の図のように、128, 256, 512bitのいづれかの文字列であるRootSeedをHMAC-SHA512(Hash-based Message Authentication Code - SHA256)というハッシュ関数に通し、出力された512bitの文字列のうち、前半256bitをマスター秘密鍵に、後半256bitを子供鍵を作るのに使うchain codeにします。

もちろん楕円曲線上のスカラー倍算を使い、この秘密鍵から公開鍵を生成できます。

(Mnemonic codeは覚えにくいSeedを英単語の列に変換して人間が覚えやすくしたものです。この章の最後の方で解説します)


次にmaster key含むそれぞれの親鍵から子供鍵を生成する仕組みを見て行きます。

上の図のように、親公開鍵・親chain code・index (32bitの数字列)をHMAC-SHA512にインプットし、そこから出力された512bitの文字列を再び前半後半に分けて、前半の256bit とインデックスが親秘密鍵と合わさって子秘密鍵になり、後半256bitは子供chain codeとなります。

インデックスを変えることで、子0、子1、子2...と子を作り出していくことができ、それぞれの親キーは最大20億個の子キーを持つことができます。 このプロセスを繰り返すことで、それぞれの子が次々に親となり自身の子供を作っていき、ツリー構造を無限に下っていくのです。


もちろんここで使われているHMAC-SHA512ハッシュ関数は不可逆関数ですので、子供は親秘密鍵を知ることも、兄弟秘密鍵を知ることもできません(樹形図を遡ることはできない)

このように無数に作られた秘密鍵から公開鍵を生成し、その公開鍵からBitcoinアドレスが生成されることで無数にBitcoinアドレスを使用できるわけです。


子供鍵を作るために必要な親秘密鍵と親chain codeのセット(indexは別になくてもいいので除外)を拡張秘密鍵と言います。

拡張鍵はBase58Checkでエンコードされ、BIP0032互換ウォレットの間でエクスポートとインポートを簡単に行うことができます。拡張秘密鍵のBase58Checkはプレフィックスとして"xprv"という特別なversion byteを使います。


以下では現在主流のウォレットであるこのHDウォレットについて少し応用的な仕組みまで見ていきます。


②拡張公開鍵の利用

HDウォレットでは、応用的な方法として親公開鍵と親chain codeから子供公開鍵と子供chain codeを生成することもできます。(秘密鍵は生成できません)

(この時に必要な親公開鍵と親chain codeのセットを拡張公開鍵という。拡張公開鍵のBase58Checkはプレフィックスとして"xpub"という特別なversion byteを使います。)


これによって公開鍵とchain codeさえ知っていれば秘密鍵を知らなくても、「公開鍵→Bitcoinアドレス」が生成できるのがHDウォレットの大きなメリットです。


これの何がいいかを具体例で説明すると以下のようになります。

仮にあなたがECサイトのオーナーで、サイトの運営を他の人(社員等)に任せたいと思っているとします。
もちろんECサイトを運営していく中では「支払い(トランザクション)を受けるためにBitcoinアドレスが足りなくなったら増やす」という行為行わなければなりません。
この時、ランダムウォレットのように「まず秘密鍵が生成されていて、そこからBitcoinアドレスを生成する方法」だと運営者が秘密鍵を知らなければいけなくなります。運営者に秘密鍵を知られると売上を持ち逃げされるリスクがあるので、あなたは運営者に秘密鍵を教えたくないですよね。
とすると、あなたが事前に沢山のBitcoinアドレスを生成しておいて、足りなくなるたびに報告を受けてあなたが秘密鍵でBitcoinアドレスを増やすというとてつもなく面倒なことをしなくてはなりません。
一方で、HDウォレットならば親公開鍵と親chain codeのみから「公開鍵→Bitcoinアドレス」が生成できるので、運営者には秘密鍵を教えることなく運営を任せることができます。


では、この「親公開鍵と親chain codeから子供公開鍵を生成する仕組み」を見て行きます。

仕組み自体は上の図のようになっています。前述した、HDウォレットの通常のBitcoinアドレス生成方法である「親秘密鍵から子供秘密鍵を生成する仕組み」を理解していればこの仕組みも理解できると思います。


ですが、なぜこれが成り立つのかという説明がmastering bitcoinには抜けていたので補足して行きます。

上の図の「親秘密鍵から子供秘密鍵を生成する(親秘密鍵拡張)」の場合は、

{A(親公開鍵と親chain codeをHMAC-SHA512に通したものの前半256bit) + B(親秘密鍵) } を 楕円曲線上のスカラー倍算したものが、子供公開鍵

です。

一方で、

この上の図の「親公開鍵から子供公開鍵を生成する(親公開鍵拡張)」の場合は、

A(親公開鍵と親chain codeをHMAC-SHA512に通したものの前半256bit) + C(親公開鍵) が子供公開鍵

とmastering bitcoinを読んでいると取れますが、これではこれらの式に矛盾が生じます。

なので、正確には

A(親公開鍵と親chain codeをHMAC-SHA512に通したものの前半256bit)を楕円曲線上のスカラー倍算したもの + C(親公開鍵) が子供公開鍵

です。(いわゆる分配法則)

上記画像(BIP32のGithub)にも [楕円曲線上のスカラー倍算]を示すpoint()が書かれていますね。


③強化子公開鍵導出

しかし、この「親公開鍵と親chain codeから子供公開鍵を生成する仕組み(親公開鍵拡張)」には大きなリスクがあります。

上の図を再確認しながらHDウォレットでもし仮に子供のsecret keyが何らかの方法で漏洩してしまった場合を考えて見ましょう。

この時、通常であれば漏洩してしまった秘密鍵以下のブランチ(漏洩した秘密鍵で生み出された子供鍵)は、乗っ取られてしまいますが、一方で、漏洩した秘密鍵以上のブランチには被害はないです。

しかし、「親公開鍵と親chain codeから子供公開鍵を生成する仕組み」を使うということは、このように生成された親子鍵のうち、「親の公開鍵」と「親のchain code」を第三者(先ほどの例ではECサイトの運営者)が知っている状態です。

この状態でその第三者に子供秘密鍵が漏洩してしまった場合は、

子供private key = HMAC-SHA512(親public key + 親chain code) + 親private key

すなわち

親private key = 子供private key - HMAC-SHA512(親public key + 親chain code)

なので

親のprivate keyが割り出されてしまい、漏洩した秘密鍵よりも上の階層まで乗っ取られてしまうのです。


このリスクを防ぐために、強化子公開鍵導出(hardened child key derivation) という手法があります。


これは第三者に拡張公開鍵として渡すブランチの子供は、特別に上の図のように、

親private key と親chain codeから生成し(この時の親private keyを"強化された秘密鍵"という)、この強化された秘密鍵から公開鍵を生成し、その公開鍵とchain codeをセットにしたものを拡張公開鍵として第三者に渡すという手法です。

これならば親publuc keyと親chain codeを知る第三者に子供private keyが漏洩したとしても、その第三者は親private keyを導くことができません。


ちなみに通常の子供鍵生成で使われるindexは0〜231-1を使用し、強化された子キーは231〜232-1のインデックスを使用します。

また、この強化された秘密鍵を使うとそれぞれの親拡張鍵は40億個の子供を持つことができます(20億個の通常の子供と20億個の強化された子供) 


④HDウォレットキー識別子(path)

もちろんですが、無数に秘密鍵が増えていくと、どこの階層の秘密鍵が何なのかを把握するのが難しくなってきます。

特定の階層に存在する特定の鍵を指定したい時は、「パスフレーズ」を用いてを鍵を一意に特定します。


パスフレーズは以下の表のように表されます。

マスター秘密鍵から生成された秘密鍵はmから始め、マスター秘密鍵から生成された公開鍵はMから始まります。

それ以降は、何番目の子供かということを0から始まる数字で表していくような形ですね。


しかし、各拡張鍵が40億個(20億個の通常の子供と20億個の強化された子供)を持つことができるため、無限に複雑に鍵のツリーが増えていくことが想定され、数字で何番目の子供かだけを表せても「その鍵の役割」を把握するのが難しくなります。


そこで、このパスフレーズの規格としてBIP44という標準規格が提案されています(他にもいろいろありますが)。

BIP44の標準規格は以下のような構造になっています。


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


 m: マスター鍵

 purpose:目的を表しますが、常に44になっています

 coin_type: Bitcoinは0, Bitcoin Testnetは1, Litecoinは2になります。ちなみにEthereumは60、Ethereum Classicは61です。

 account:口座番号のようなものです。これによってユーザが複数の口座を使えるようにし、会計や組織的な目的で使えるようにしていま す。それぞれの口座はそれぞれ自身のサブツリーのルートになっています。

change:お釣りを受け取るためのBitcoinアドレスかどうかを表します。外部送金者からの受け取りが0, 自身のトランザクションからのおつりの受け取りが1になります。この項目があるのは、大抵の場合、プライバシー保護のために、送金時のお釣りは元のアドレスに戻すのではなく新規にお釣り用アドレスが作成されるためです。

address_index:これはその口座の中の受け取りアドレス番号です。


このように各層に決まった情報を書くことによって、その階層にある鍵の役割や性質が一目で分かるようにしています。


BIP44規格の例は以下の画像のようになります。



⑤Mnemonic Codeとは?

HDウォレットのSeedは

3338a6d2ee71c7f28eb5b882159634cd46a898463e9 d2d0980f8e80dfbba5b0fa0291e5fb88 8a599b44b93187be6ee3ab5fd3ead7dd646341b2cd b8d08d13bf7

のような文字列なので、これを覚えておくために転写する際に書き間違いや打ち間違いなどが生じかねません。

そこでBIP(Bitcoin Improvement Proposal)39で提案されているのが、Mnemonic Code(ニモニックコード:記憶を助けるコード)です。


Mastering Ethereum から引用した図を見ながらMnemonic Codeが生成される仕組みを説明します。

Mnemonic Code とはそもそもSeedを生成する際に、


  • 1. 128bitから256bitの暗号学的に安全な乱数(エントロピー:不規則性を表す量、乱雑さ)を生成
  • 2. 1のSHA256ハッシュの先頭4bitを取得し、1のチェックサムを生成
  • 3. このチェックサムを1の最後に付加 (チェックサムは与えられた英単語列が本当にこの手順に従って生成されたものであるかを確認するためのものでしたね)
  • 4. 2048個のあらかじめ決められた英単語の辞書のインデックスとして使うために、この配列を11bitずつの 部分に分割
  • 5. mnemonic codeを表す12から24個の英単語をそれぞれ11bitに当てはめ、12個から24個の英単語配列を生成
  • 6. こうして生成した「Mnemonic Code」と「"mnemonic" という文字列にUserが設定したパスワードをくっつけた文字列 」をPBKDF2というHMAC-SHA512 algorithmを使ったキー拡張関数に通すことで長いシード(512bit)を生成


というプロセスを経ることによってSeedとMnemonic Codeが作られます。


こうすることでSeed = mnemonic code(12 ~ 24個の英単語)として表せるため、Seedが人間にとって転写や記憶がしやすいものになるという仕組みです。


例 )

Seed : 3972e432e99040f75ebe13a660110c3e29d131a2c80 8c7ee5f1631d0a977fcf473bee22 fce540af281bf7cdeade0dd2c1c795bd02f1e4049e20 5a0158906c343

英単語列: cake apple borrow silk endorse fitness top denial coil riot stay wolf luggage oxygen faint major edit measure invite love trap field dilemma oblige


ウォレットを使ったことのある人なら絶対に忘れてはならない鍵としてこのような英単語の列をどこかにメモした経験があるのではないでしょうか。



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

HDウォレットのメリットとデメリットを整理してみます。


メリット

  • 覚えておかねばならない対象がSeedのみのため管理が楽
  • ウォレット移行の際にSeedのみを移行すれば良いのでとても楽
  • 樹形図構造になっているので、「特定の鍵階層(ブランチ)以下を特定の役割(会社の部署など)に割り振る」などができる
  • 第三者(会社であれば部署ごとの社員)にツリー構造のブランチの拡張公開鍵だけを渡して運営を任せられる

デメリット

Seedを紛失もしくは盗難された場合には、そのSeedから生成した生成した全てのBitcoinアドレスに紐づくビットコインが失われてしまう



(5)高度なキーとアドレス

①暗号化秘密鍵(BIP0038)

秘密鍵は極秘にしておかなければならないと言っても、完全に極秘にすることは難しいと思います。

そこで提案されたのが暗号化秘密鍵(BIP0038)です。


BIP0038は、安全なバックアップメディアへの保存およびウォレット間の転送ができるように、またキーが晒される可能性のある状況にも対応できるように、パスワードで秘密鍵を暗号化(Advanced Encryption Standard (AES)という暗号化基準)し、さらにBase58Checkでエンコードするという標準規格です。


通常言われている秘密鍵は、インプットとしてBitcoin秘密鍵を取り、プレフィックス "5" を伴ったBase58Checkを使いWallet Import Format (WIF)にエンコードされたものです。

BIP0038暗号化スキームでは、アルファベットと数字が混ざった複雑な文字列で構成される 長いパスワードを使って暗号化したこのようなBIP0038暗号化スキームの結果として、 6P から始まる Base58Checkでエンコードされた暗号化秘密鍵が得られます。もしキーが 6Pから始まっていれば、それは暗号化されており、どのウォレットでも使えるWIF形式秘密鍵(5 から始まるもの)に戻すためにはパスワードが必要になります。


②Pay-to-Script Hash (P2SH) とマルチシグネチャアドレス

通常のBitcoinアドレスは“1”から始まり、これは“送る”トランザクション(pay-to-public-key-hash (P2PKH))です。

このbitcoinは対応する秘密鍵署名と 公開鍵ハッシュを使うことでのみ使用できます。


一方で、“3”で始まる Bitcoinアドレスに送った資金のトランザクションでは、公開鍵ハッシュと秘密鍵署名以外の別のものも要求され得ます。ここで要求されるものはBitcoinアドレスを作ったときにscriptの中で指定されるものです。


P2SHアドレスは、通常のBitcoinアドレスを生成するときに使われる二重ハッシュ関数と同じ関数を、公開鍵の代わりにscriptに適用して生成されます。

そうして出力された"script ハッシュ"はversion prefix 5でBase58Checkエンコーディングされ、その結果として3 から始まるアドレスになります。


P2SHアドレスの例:32M8ednmuyZ2zVbes4puqe44NZumgG92sM


P2SHアドレスには、あらゆるスクリプトが使われ得ますが、現在最も一般的なのがマルチシグネチャアドレスです。

マルチシグネチャアドレスのscriptは所有権を証明し資金を利用するために1つ以上の署名を要求するというものです。

2 of 3などが最も一般的で、この場合は、そのアドレスが保持している資金を引き出すための署名が3つ存在しており、そのうちの2つが揃えば、資金が引き出せます。


これらに関しては第5章の後半で詳しく解説します。


③Vanity Address (虚栄アドレス)

Vanityアドレスは、人間が意味を読み取ることのできるメッセージを含んだBitcoinアドレスのことです。

例えば発展途上国の子供支援の募金を募るBitcoinアドレスの最初の5文字を"1Kids"にするなどの用途があります。


このようなVanityアドレスの作り方は

望んだ文字列パターンのBitcoinアドレスが出るまで「秘密鍵生成→公開鍵生成→Bitcoinアドレス生成」をひたすら繰り返す

という地味なものです。笑


望む文字列が長ければ長いほど、出る確率が低くなるので、マイニングに使えなくなったGPUなどをVanityアドレスの生成に使っている業者もあったりするそうです。笑


④ペーパーウォレット

紙に「Bitcoinアドレス」と「秘密鍵(WIF) または 暗号化された秘密鍵」を印刷したもので、

完全にオフラインなので究極のコールドストレージ(コールドウォレット)と言われています。



<感想>

HDウォレットの仕組みの部分が結構重かった。

SHA256、楕円曲線暗号、RIPEMD160、HMAC-SHA256についてはさらに深掘って別途記事にまとめたい。


続き↓


0コメント

  • 1000 / 1000