- 作者: アンドレアス・M・アントノプロス,今井崇也,鳩貝淳一郎
- 出版社/メーカー: エヌティティ出版
- 発売日: 2016/07/14
- メディア: 大型本
- この商品を含むブログ (7件) を見る
関連記事
- 「Mastering Bitcoin」を読む (第1章 イントロダクション・第2章 ビットコインの仕組み)
- 「Mastering Bitcoin」を読む (第4章 鍵、アドレス、ウォレット)
- 「Mastering Bitcoin」を読む (第5章 トランザクション)
- 「Mastering Bitcoin」を読む (第8章 マイニングとコンセンサス)
これは著者が読んだ内容をまとめているだけなので、誤訳、理解不足により誤っている可能性があります!鵜呑みにしないようにお願いします。 文章の途中に挿入している画像は、 https://www.bitcoinbook.info/translations/ja/book.pdf に含まれている画像を使用させていただいています。
第03章 ビットコインクライアント
クライアントの使い方がメインなので省略。
第04章 鍵、アドレス、ウォレット
イントロダクション
ビットコインの所有権の基礎 : 「デジタル鍵」「ビットコインアドレス」「デジタル署名」
公開鍵暗号と暗号通貨
公開鍵、秘密鍵、ビットコインアドレスの関係性
- 秘密鍵はランダムに生成される値である。このアドレスをもとに公開鍵とビットコインアドレスが生成される。
- 秘密鍵は所有権そのものを意味する。秘密鍵の値が漏れてしまうと、所有権が移されてしまうのと同義である。
秘密鍵の生成
正確には、秘密鍵は1から までの任意の整数である。 は楕円曲線の異数であり、 よりもわずかに小さな値である。
公開鍵
楕円曲線上のスカラー倍算を使って秘密鍵から生成する。これは不可逆の計算である。 、 は秘密鍵、 は生成元と呼ばれる定点、 は公開鍵となっている。
この公開鍵は一方向でのみ導出することができ、公開鍵から秘密鍵を導出することができない。 また、公開鍵から生成されるビットコインアドレスからも、秘密鍵が計算することができないため、ビットコインアドレスは誰と共有しても問題とならない。
楕円曲線暗号
ビットコインの楕円曲線暗号は、米国国立標準技術研究所(NIST)のsecp256k1という標準で定義された楕円曲線と定数を使っている。
$$y^{2} = \left(x^{3}+7\right) \text{over} (F_p)$$
または、
$$y^{2} \mod p = (x^{3}+7) \mod p$$
として定義される。ここで は として定義される非常に大きな素数である。
例えば、以下のは楕円曲線上の点である。Pythonを使って確かめる。
P = (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424)
>>> P = [55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424] >>> p = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1 >>> (P[0]**3+7 - P[1]**2)%p 0
※ 注記 : 楕円曲線暗号での計算の方法は、以下のサイトが分かりやすかった。
https://btcnews.jp/elliptc-curve-diy/
ビットコインアドレス
ビットコインアドレスとは、資金の受取人としてトランザクションに登場する。 数字と文字で構成された文字列。
さらに、ビットコインアドレスはBase58Checkと呼ばれる形にエンコードされる。 これは、可読性を上げ、転写時のエラーを防ぐ目的がある。
Base58 と Base58Checkエンコード
Base64エンコードは、もともとE-mailなどでバイナリを送信するために利用されているエンコードだが、Base58はよりコンパクトで、可読性、エラー防止などの機能をバランスよく提供している。 - 0(ゼロ)、O(大文字のオー)、l(小文字のエル)、I(大文字のアイ)、記号「+」や「/」を除去したものである。
さらに、書き間違いや転写間違いを防ぐために、Base58にチェックサムが組み込まれている。これがBase58Check。
- データの先頭に"version byte"というプレフィックスを追加する。
checksum = SHA256(SHA256(prefix+data))
生成される32バイトのハッシュ値から最初の4バイトだけを取り出す。
鍵フォーマット
人々が鍵を間違えずに容易に読み転写できるようになることを第一の目的として用いられている。
秘密鍵フォーマット
秘密鍵を表現するために使われる3つの形式として、「16進数」「WIF」「圧縮WIF」が用いられる。
公開鍵フォーマット
公開鍵は楕円曲線上の点であり、 の形式で表現されている。さらに、プレフィックス04が付加されている。
以下の秘密鍵から生成した公開鍵は、プレフィックス04が付加されて以下のように公開鍵となる。
x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
圧縮された公開鍵
公開鍵のサイズを圧縮するために、 のうち のみを保持するという方法がある。 これは、楕円曲線の上に載っている場合、 が分かれば も計算可能であるという原理に基づいている。 具体的には、 を解くことで、 を計算することができる。 これにより公開鍵のサイズを50%圧縮することができる。
しかし、 から を導こうとすると平方根の関係上正負の値が生成されてしまうため、 座標の符号は省略できず、保存する必要がある。 座標は偶数または奇数になり、これは正負に対応している。 したがって、 が偶数ならば02を、奇数ならば03を公開鍵の先頭に付与する。
以下が圧縮された公開鍵である。
K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
圧縮された公開鍵は一般的に使用されるようになっているが、圧縮された公開鍵に対応していないクライアントから転送されたトランザクションに対応するために、そのトランザクションを解釈する必要がある。
秘密鍵をウォレットからエクスポートする場合、これまでとは異なるWallet Import Formatを使用する。 圧縮された公開鍵が秘密鍵から作られていることを示しており、ビットコインアドレスが圧縮されているということをが示されている。
圧縮された秘密鍵
秘密鍵自体は圧縮されておらず、圧縮することができない。 このため、圧縮された秘密鍵というのは、実際には秘密鍵の最後に01を付加したものになっており、秘密鍵よりも1バイト長いものになっている。
圧縮された公開鍵を実装した新しいウォレットでは、秘密鍵はWIF圧縮形式(先頭がKまたはL)でエクスポートされるが、そうでなければWIF形式(先頭が5)でエクスポートされる。
鍵とビットコインアドレスのPythonでの実装
ウォレット
非決定性ウォレット
- ランダムに生成された鍵を使用する。
- この場合の欠点は、鍵がバックアップされておらずその鍵を紛失した場合には、すべての資産を紛失することになるというものである。
- 非決定性ウォレットを使ってしまうと、トランザクションの度に別の鍵を作成し、そのすべてを管理しなければならなくなり、複雑になってしまう。
決定性ウォレット
Mnemonic Code Words
- 決定性ウォレットを生成する際にシードとして使った乱数を表現するための、英単語の列。
階層的決定性ウォレット (Hierarchical Deterministicウォレット : HDウォレット)
- 親鍵が子鍵群を生成する。
- ツリー構造であることにより、特定の機能ごと、口座ごとに「ブランチ」を割り当てることができる。
- 秘密鍵にアクセスすることなく、ユーザが公開鍵を生成することができる。
シードからHDウォレットの生成
- HDウォレットは、ルートシードから生成する。
- ルートシードをHMAC-SHA512アルゴリズムに入力される。
子秘密鍵の導出
- 子鍵導出関数は、以下を組み合わせた一方向ハッシュ関数となっている。
- 親秘密鍵または親公開鍵 (ECDSA非圧縮鍵)
- chain code(256ビット)と呼ばれるシード
- インデックス (32ビット)
- インデックスを変えることで、いくつもの子鍵を作ることができる。
導出された子鍵の使用
拡張鍵
- 子鍵生成に必要な、本質的なインプットは、鍵とchain codeであるため、これを組み合わせて拡張鍵とする。
- 拡張秘密鍵 : 秘密鍵とchain codeを組み合わせて、子秘密鍵を生成する。さらに、子秘密鍵から子公開鍵を生成する。
- 拡張公開鍵 : 公開鍵とchain codeを組み合わせて、子公開鍵を生成する。
- この、秘密鍵を使うことなく、親公開鍵から、子公開鍵を生成できるという特徴を持っている。
子公開鍵の導出
- 秘密鍵を持たないサーバにおいても、拡張公開鍵を持っていればいくらでも公開鍵を生成することができる。
- Eコマースなどで、サーバ内で公開鍵が生成できるようになる。
強化子公開鍵
- 万が一子秘密鍵が漏洩してしまった場合、すべての子秘密鍵を漏洩できる危険性がある。
- これを防ぐために「強化導出」というものを使っている。
- 親公開鍵と子chain codeの関係を壊す。
- 親公開鍵の代わりに、親秘密鍵を使って子chain codeを導出する。
高度な鍵とアドレス
暗号化秘密鍵
- 秘密鍵を、暗号化パスフレーズを使って暗号化する。
- 暗号化秘密鍵を生成することによって、秘密鍵を紙にバックアップすることができるようになる。
- オフラインビットコインストレージを作るための最良の方法である。
Pay-to-Script Hash(P2SH)とマルチシグネチャアドレス
- 3から始まるビットコインアドレスはpay-to-script hash(P2SH)アドレス
Vanity Address
- ビットコインアドレス内に、人間の読み取ることのできる文字列を挿入する。
- これにより、慈善団体が寄付を募るためのコードに、任意の文字を入れることができる。
- ただし、このようなVanity Addressを探し出すためには、一つずつ計算を行っていく必要があり、5~6文字以上は現実的ではない。
Vanity Addressのセキュリティ
- このVanity Addressを悪意のある人間が誤用させるためには、Vanity Adressの文字列の部分を長さ+2くらいの長さの似たようなビットコインアドレスが必要になる。
- 8文字のVanity Addressを含むアドレスを生成したらならば、悪意のある人間は+2の10文字を生成する必要がある。これは現実的ではない。
- より長いVanity Addressを生成すると、悪意のある人間もそれに伴って多くの計算量が必要となる。
ペーパーウォレット
- 秘密鍵を紙に印刷する。
- コールドストレージとして機能する。