初めに
最近話題のBitcoinですが、いざ仕組みを調べてみようと思うと、非技術者向けの例え話や暗号理論に偏りすぎているものが多くて、なかなか実像を掴みにくいです。
そこで、この記事では1つ1つコードで実装しながら段階を踏んで、実際に使用できるBitcoinアドレスを生成していきます。
生成アルゴリズム
準備
鍵の生成
まずは、ECDSA sampleで鍵のペアを生成します。このとき、curveはsecpk1-256を選んでください。
また、クライアントサイドで生成しているとのことなので、秘密鍵の流出については大丈夫かと思われますが、心配な方はopensslでローカルで生成してください。
関数の準備
byte列を扱う上で、必要となる関数を先に定義しておきます。
;; "0cab3f...."というbyte列の文字列をbyteのシーケンスに変換
(defn read-byte [x]
(->> (partition-all 2 x)
(map (partial apply str))
(map hex2dec)
(map byte)))
;; (read-byte "0cab3f")
;; => (12 -85 63)
;; "0cab3f...."というbyte列の文字列をbyte-arrayに変換
(defn read-bytes [x]
(->> (partition-all 2 x)
(map (partial apply str))
(map hex2dec)
(map byte)
byte-array))
;; (read-bytes "0cab3f")
;; => #object["[B" 0x36519d "[B@36519d"]
(defn hex2dec [x]
(let [n (Long/parseLong x 16)]
(if (>= n 128) (- n 256) n)))
鍵の定義
(def pubkey "0452fc6e03ce4d2125167a16...")
(def prvkey "02f29aae71872ed03b32b460...")
生成
呼称
これ以降は、SHA256->RIPEMD160をHash160、SHA256->SHA256をHash256とします。
また、Hash #1-2 を主ハッシュ、Hash#2-2をチェックサムと呼びます。
Hash160
(require '[pandect.core :as p])
(defn hash160 [value]
(-> value (p/sha256-bytes) (p/ripemd160)))
Hash256
(defn hash256 [value]
(-> value (p/sha256-bytes) (p/sha256)))
base58
(def base-string "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
(defn int-to-base58 [num leading-zeros]
(loop [acc [] n num]
(if (pos? n)
(let [s (nth base-string (rem n 58))]
(recur (cons s acc) (quot n 58)))
(apply str (concat (repeat leading-zeros (first base-string)) acc)))))
(defn encode [bytes]
(let [leading-zeros (->> bytes (take-while zero?) count)
n (java.math.BigInteger. 1 (byte-array bytes))]
(int-to-base58 n leading-zeros)))
参考: dbasch/base58
主ハッシュ
(defn gen-main-hash [k]
(str nw-id (hash160 (read-bytes k))))
チェックサム
(defn gen-checksum [k]
(->> (hash256 (read-bytes (gen-main-hash k)))
(take 8)
(apply str)))
アドレス
(defn gen-address [k]
(->> (str (gen-main-hash k) (gen-checksum k))
read-byte
encode))
実際に生成
(gen-address pubkey)
=> "1MGmkfg9kse2Aribbg2fWGGRGqhVxCFetF"
検証
生成したアドレスの検証はBlockExplorerで行います。
https://blockexplorer.com/address/生成したアドレス に飛ぶと、正当なアドレスならトランザクションやQRコードが表示されます。
例: https://blockexplorer.com/address/1MGmkfg9kse2Aribbg2fWGGRGqhVxCFetF
参考文献
bitcoinwiki
Bitcoinを技術的に理解する
ビットコインの仕組み
Mastering Bitcoinを読む Chapter4 公開鍵、ビットコインアドレス
dbasch/base58