2017/04/06

[bc]アドレスを作るまでの計算

前回は、Bitcoinのアドレス、と一言にいってもいろいろ種類がありますよ、ということを書いた。
そして、先頭の文字を見ると、だいたいどういう種類かや、お金に関わる方のBitcoinブロックチェーン(mainnet)なのか、お金が関わらない方のBitcoinブロックチェーン(testnet)なのかわかる、というところまで説明した。

 

わざわざ「Bitcoinのブロックチェーン」と書いているように、ブロックチェーンにもいろいろ種類がある。
というよりも、それぞれ別のブロックチェーンのネットワークを作っている。
例えば、mainnetとtestnetは、ブロックチェーンの構造としては同じだが、TCP/IPのポート番号が異なる。
Ethereumという、こちらも有名なブロックチェーンを使った仮想通貨があるが、これはこれで別のブロックチェーンだ。

「ブロックチェーン」という1つのものをみんなが使っているわけではなく、めいめいが自分が好きなようにブロックチェーンを作っているのである。


では、話を戻そう。

Bitcoinアドレスは、似たような文字列でできているように見えるが、そもそもどうやってアドレスを作っているのか、という話をしたい。

http://chimera.labs.oreilly.com/books/1234000001802/ch04.html
ここに全部書いてあるので、読むとわかる。

・・・ではあんまりなので、大雑把に説明しよう。
なお、私はtestnetでしかやってないので、説明もtestnetだ。

 

Pythonでの実装例がExample4-4に載っているので、それを見ていこう。
http://chimera.labs.oreilly.com/books/1234000001802/ch04.html#_implementing_keys_and_addresses_in_python

まず、32byteの乱数を用意する。
16進数32個分だ。
http://chimera.labs.oreilly.com/books/1234000001802/ch04.html#ec_math
Example4-6の、

byte_array = os.urandom(32)

がそれにあたる。
この値を「秘密鍵(private key)」と呼ぶ。

 

秘密鍵は単なる大きい値というだけで、この次に楕円曲線暗号というものが出てくる。
楕円、ではなく、楕円曲線、だ。
金魚鉢のような、オバQのO次郎を横向きにしたような、そんな形だ(Figure 4-2)。
http://chimera.labs.oreilly.com/books/1234000001802/ch04.html#pubkey

楕円曲線にもいろいろ種類があるのだが、とにかくBitcoinで使用する楕円曲線上の点Gに、楕円曲線座標系での乗算を行うことで「公開鍵(public key)」が求められる(Figure 4-4)。
もちろん、点Gに掛けるのは秘密鍵だ。
http://chimera.labs.oreilly.com/books/1234000001802/ch04.html#ecc_illustrated
この図では、G→-2G→+2G→-4G→+4G→-8G→+8G、という演算が行われている。
もし秘密鍵が「8」だったら、この8Gが公開鍵の座標になる。
なんで接線方向に移動したりX軸に直角に移動したりするの?と問われても、私にはわからん。。。

公開鍵は座標なので、(x, y)の形式になる。
ノーマル形式の公開鍵は、このxとyを連結した値になる。
秘密鍵が32byteだからか、xも32byte、yも32byteにするようで、連結すると64byteになる。
それだけだとなんだかわからないので、「0x04」を頭につけて「ノーマル形式の公開鍵」という表現の仕方をすることになっている。
だから、65byteだ。

ただ、楕円曲線を見るとわかるように、X軸に対して線対称だ。
では、X座標とそれに対応するY座標の正負情報だけで公開鍵を表して短くしよう、という説明がFigure 4-7だ。
http://chimera.labs.oreilly.com/books/1234000001802/ch04.html#pubkey_compression
x座標からy座標を求める演算はy2 mod p = (x3 + 7) mod pになるため、y2を解くと±の結果になるから、どっちなのよ、ということを示すために、ノーマル形式の「0x04」に対して「0x02」 or 「0x03」という値を頭につけて、33byte形式にしたのが「圧縮された公開鍵」と呼ばれるようになっている。
今では、「0x04」の公開鍵はデータが大きくなるのでほぼ使われていないと思う。

 

公開鍵に、SHA256というハッシュ計算をすると、32byteになる。
それにRIPEMD160というハッシュ計算をすると、20byteになる。
理由は知らんが、Bitcoinではハッシュ計算を2回連続して行うことが多い。
ともかく、公開鍵をSHA256→RIPEMD160、という計算で出てきた20byteの値を公開鍵ハッシュ(Public Key Hash)と呼ぶ。
通称、PubKeyHash。
略称、PKH。

 

PKHに、前回出てきたmainnet/testnetのプレフィクスをつけ、CRCをサフィックスにつけ、それをBase58Checkというエンコード方式で演算すると、Bitcoinアドレスが出てくる。
Base64という、メール添付するときのエンコード形式から、目で見て見分けにくい文字を減らして58文字にしたのがBase58らしい。
Base58はハッシュではなくエンコード/デコードなので、今回で言えばBitcoinアドレスから公開鍵ハッシュまで戻すことはできる。
http://lenschulwitz.com/base58

 

公開鍵を公開鍵ハッシュにした値からアドレスを求めるので、このアドレス方式はPublic to Public Key Hash→P2PKHと呼ばれる(のだったと思う)。

このようにして、秘密鍵、公開鍵、公開鍵ハッシュ、Bitcoinアドレス(P2PKH)が得られる。
お疲れ様でした。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。