見出し画像

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の記事ネタになりそうな書籍の購入などに使わせていただきます!