LoginSignup
8
7

More than 5 years have passed since last update.

ClojureでBitcoinアドレスを生成する

Posted at

初めに

最近話題のBitcoinですが、いざ仕組みを調べてみようと思うと、非技術者向けの例え話や暗号理論に偏りすぎているものが多くて、なかなか実像を掴みにくいです。
そこで、この記事では1つ1つコードで実装しながら段階を踏んで、実際に使用できるBitcoinアドレスを生成していきます。

生成アルゴリズム

bcadd.png

準備

鍵の生成

まずは、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

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7