Python3で秘密鍵からビットコインアドレスを作る
秘密鍵からビットコインアドレス(P2PKH)を作ってみます。今回は、言語としてはPython3を使います。
ビットコインアドレスがどのように作られているかは、Mastering Bitcoinなどを参照してください。
準備
ライブラリとしては以下の3つを使います。
import hashlib
import ecdsa
import base58
ライブラリの関数をそのまま使うとコードが見にくくなるので、SHA256、RIPEMD160、Base58エンコードの関数をそれぞれ定義します。
def sha256(b):
return hashlib.sha256(b).digest()
def ripemd160(b):
h = hashlib.new('ripemd160')
h.update(b)
return h.digest()
def base58encode(b):
return base58.b58encode(b).decode()
秘密鍵から公開鍵へ
本題に入ります。まず、秘密鍵から公開鍵を作る関数が必要です。楕円曲線暗号を用いた署名アルゴリズムを使います。ビットコインではsecp256k1をパラメータとしています。非圧縮の形式であることを示す4を先頭に追加しています。ecdsaライブラリのおかげで、こんな感じで書けます。
def pubkey(secret_key):
b = secret_key.to_bytes(32, 'big')
sk = ecdsa.SigningKey.from_string(b, curve=ecdsa.SECP256k1)
vk = sk.get_verifying_key()
return b'\04' + vk.to_string()
公開鍵からビットコインアドレスへ
公開鍵ができたら、ビットコインアドレスを求められます。
公開鍵にsha256とripemd160を適用して、バージョン番号として0を先頭に加えて、チェックサムを加えてbase58エンコードを適用し(base58checkとか言います)、人間が扱いやすくしたものがビットコインアドレスです。コードで書くとこうなります。
def address(public_key):
addr = b'\00' + ripemd160(sha256(public_key))
checksum = sha256(sha256(addr))[:4]
return base58encode(addr + checksum)
これで完成です!
動作確認
試しに、秘密鍵を1にして、ビットコインアドレスを求めてみましょう。
>>> address(pubkey(1))
'1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm'
はい、とても危険なアドレスが出来上がりました。このアドレスに送金すると、あっという間にどこかに盗まれていくようですね。
もうひとつやってみましょう。"satoshi"のハッシュ値をビットコインアドレスにしてみます。
>>> satoshi = int.from_bytes(sha256(b'satoshi'), 'big')
>>> address(pubkey(satoshi))
'1ADJqstUMBB5zFquWg19UqZ7Zc6ePCpzLE'
これも、同じくとっても危険なアドレスのようですね。簡単にわかる秘密鍵は、世界中から狙われているということでしょう。
ビットコイン的には、秘密鍵を持つ人が本人ということになるので、「盗んだんじゃない、自分のビットコインをただ送金しただけだ!」ということになるのかもしれませんが。
よろしければサポートお願いします。研究やnoteの記事ネタになりそうな書籍の購入などに使わせていただきます!