秘密鍵
まずビットコインの秘密鍵は下記のように64個の16進数で表され、256ビットの整数となります。1から2256の間の数字から一つの数字を選ぶということと同じで非常に大きい数字を扱っていることが想像できると思います。
1A09347FBE2375A34CABC6D7812AB32E4F4245BE1A095E1ACB5634562BC2356
公開鍵
公開鍵は楕円曲線上のスカラー倍算を使って、以下の式で秘密鍵から計算されます。秘密鍵はこの逆の計算からも求めることはできません。
K = k * G // K: 公開鍵 k: 秘密鍵 G: 生成元
ビットコインで使われる楕円曲線暗号
ビットコインでは楕円曲線が使用されていて、一般的な式は下記です。
y2 = x3 + ax + b
ビットコインではa = 0、b = 7でmod pしたsecp256k1という特殊な楕円曲線を使用しています。pは素数で2256 – 232 – 29 – 28 – 27 – 26 – 24 – 1となっています。生成元(ベースポイント)Gのx,y座標はそれぞれ下記のようになっています。
Gx: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Gy: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
y2 = (x3 + 7) over (Fp)
or
y2 mod p = (x3 + 7) mod p
mod pする前の関数のグラフは以下のように滑らかなグラフとなっていますが、mod pをすることで曲線上の点が離散的な値を取るようになります。このように離散的な値を取ることで離散対数問題となり、公開鍵から秘密鍵を求めることを難しくしています。
離散対数問題(discrete logarithm problem)とはxからyを計算するのは容易だが、yからxを求めるのは非常に困難であるという数学的性質のことです。

bitcoinwiki参照より参照。
生成方法
公開鍵は上記K=k*Gで求めることができ、Gはビットコイン全ての鍵に対して常に同じとなっています。なので秘密鍵が分かれば公開鍵は一意に求めることができるようになっています。また、公開鍵はこの楕円曲線上の(x, y)座標として定義されます。
Gをk回足すというのは、楕円曲線において、ある点の接線が楕円曲線で交わる点を求め、その交点をX軸に対して対象に移動した点を見つけることをk回行うことと同義となります。
ビットコインアドレス
ビットコインアドレスは公開鍵を一方向の暗号学的ハッシュ化を行うことで生成します。なので、秘密鍵と公開鍵の関係と同じようにアドレスから公開鍵を求めるのは非常に困難となっています。
下記はビットコインアドレスのサンプルです。ビットコインアドレスは先頭に数字の1が付きます。
1rdaQ7yvg28uh54gaXww6fupmfgr98wkmn
アドレスの生成
アドレスを生成するときに使用するハッシュ関数はsha256とRIPEMD160を使用し、160ビット(16進数だと40桁)の数字を生成します。double hashとは公開鍵をsha256とRIPEMD160で合わせて2回ハッシュ化を行うのでそのように呼ばれています。

Base58とBase58Check
上記のダブルハッシュ化の後にさらに一手間加えます。それがBase58Checkエンコードです。Base58エンコードは可読性や送信アドレスの間違いを防止する機能を持った、ビットコインの為に開発されたエンコード形式となります。
エンコードには0~9、a~z、A~Zの62種類から0(ゼロ)、O(大文字のオー)、l(小文字のエル)、I(大文字のアイ)を除いた58種類の文字と数字を使います。さらにBase58にチェックサムが組み込まれたものをBase58Checkと言います。
Base58Checkエンコードの流れは下記のようになります。

まず、sha256とRIPEMD160でハッシュ化した公開鍵(Payload)をsha256で2回ハッシュ化を行います。これをダブルハッシュと呼びます。ハッシュ値の先頭4バイトをPayloadの後ろに付け、先頭にはVersion Preifxというものを付けます。
version prefixは下記です。
種類 | Version Preffix | Base58出力文字列の先頭につけられるプレフィックス |
ビットコインアドレス | 0x00 | 1 |
Pay-to-Script-Hashアドレス | 0x05 | 3 |
ビットコインTestnetアドレス | 0x6Ff | m または n |
秘密鍵WIF形式 | 0x80 | 5, K または L |
BIP28暗号化秘密鍵 | ox0142 | 6P |
BIP32拡張公開鍵 | 0x0488B21F | xpub |
これらを全て合わせた状態でBase58Checkエンコードを行うことでよく見るビットコインアドレスとなります。
まとめ
秘密鍵、公開鍵、アドレスと理論的な生成方法を見てきましたので、今後はソースコードを交えて実際に秘密鍵からアドレスまで生成して見たいと思います。
最後にブロックチェーンエンジニアって何?どうやったらなれるの?という人向けに書いた下の記事も読んでみてください。
おすすめ書籍
ビットコインとブロックチェーンの詳細をしっかりと学びたい方にはこちらの書籍が非常におすすめです。ウォレットの仕組み、楕円曲線暗号、P2Pプロトコル、公開鍵暗号などビットコインを支える技術について詳細に解説されています。また、サンプルコードを通して実際に手を動かして学べるので非常に濃い内容となっています。
こちらはブロックチェーンの初学者向けになります。ブロックチェーンの応用例の紹介から基礎的な理論まで分かりやすく図解で解説されています。また、ビットコインやEthereum、HyperLdger Fabricを実際に稼働させてみて動作を理解するためのサンプルコードの解説もあります。
髙妻智一
最新記事 by 髙妻智一 (全て見る)
- Polkadot(Substrate)のアドレスとトランザクションについて - 2023-03-09
- 【無料公開】「Goで始めるBitcoin」3章 Bitcoinノードとの通信 技術書典8 - 2020-03-08
- エンジニアがゼロから技術ブログを書くための方法をまとめました - 2019-05-25
コメントを残す