【Python】ビットコインアドレス 作りました
はじめに
ビットコインとは簡単にいうと「中央集権者を媒介せず素早く通貨を送金する」ための暗号通貨のプラットフォームです。
暗号通貨を安全に保管するためにはウォレットサービスを用います。
ウォレットサービスの立ち位置としては「財布」というより「秘密鍵の保管場所」となります。
暗号通貨の取引が発生する際、トランザクションの署名と検証が行われるのですがその際に秘密鍵が使用されます。
暗号通貨の取引(トランザクション)、例えばアリスさんがボブさんに1 BTC
送金する際に必要なのが両者のビットコインアドレス(ウォレットアドレス)です。
環境
WSL2
Ubuntu 20.04 on Windows(11)
実装方針
- 秘密鍵を作る
- 公開鍵を作る
- ビットコインアドレスを作る
プロジェクトのセットアップ
利用するモジュール
import secrets
import ecdsa
import hashlib
import base58
ターミナルで実行
sudo apt install python3-pip
sudo pip install ecdsa
sudo pip install base58
大枠のソース
# 主コード
class generateWalletAddress():
def __init__(self):
p = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
privateKey = self.getPrivatekey(p)
publicKey = self.getPublickey(privateKey)
walletAddress = self.getWalletAddress(bytes.fromhex("00"), publicKey)
def getPrivatekey(self, p):
def getPublickey(self, privateKey):
def getWalletAddress(self, version, publicKey):
# WAを作成するに当たり関数を呼び出す
walletAddress = generateWalletAddress()
秘密鍵を作る
秘密鍵とは1~2^256までの整数値です。
2^256 より微小な数値をp(=2^256-2^32-2^9-2^8-2^7-2^6-2^4-1)と定義します。
secrets.randbelow(n)メソッドの引数にpを渡して、ランダムな整数を取得し秘密鍵を生成します。
def getPrivatekey(self, p):
# 秘密鍵はpより小さな数字を選択する
privateKey = secrets.randbelow(p)
# 16進数表示に変換
privateKey = format(privateKey, 'x')
print("秘密鍵が生成されました:" + privateKey)
return privateKey
公開鍵を作る
作成した秘密鍵とECDSAを用いて公開鍵を生成します。
def getPublickey(self, privateKey):
# 16進数からバイト列に変換
bin_privateKey = bytes.fromhex(privateKey)
# ECDSAを用いて楕円曲線から公開鍵となる値を計算
signing_key = ecdsa.SigningKey.from_string(bin_privateKey, curve = ecdsa.SECP256k1) # メソッドの指定
verifying_key = signing_key.get_verifying_key()
# 文字列の操作
publicKey = bytes.fromhex("04") + verifying_key.to_string()
publicKey = publicKey.hex()
print("公開鍵が生成されました:" + publicKey)
return publicKey
ビットコインアドレスを作る
公開鍵をハッシュ化してチェックサム処理(処理中に対象の値が意図しない誤った値となった場合に検出するための仕組み)を媒介して例外を消し、Base58でエンコーディングしてビットコインアドレスを生成します。
def getWalletAddress(self, version, publicKey):
ba = bytes.fromhex(publicKey)
# sha256でハッシュ化してできたものを文字列変換
digest = hashlib.sha256(ba).digest()
new_digest = hashlib.new('ripemd160')
new_digest.update(digest)
publicKey_hash = new_digest.digest()
# main/testをversion指定する
pre_address = version + publicKey_hash
address = hashlib.sha256(pre_address).digest()
address = hashlib.sha256(address).digest()
checksum = address[:4]
address = pre_address + checksum
# bitocoin特有のベースエンコーディング
address = base58.b58encode(address)
address = address.decode()
print("Address = " + address + "\n")
return address
おまけ
ビットコインが仮想通貨の送受信に注目した暗号通貨プラットフォームである一方で、
イーサリアムは暗号通貨ではなくスマートコントラクトをブロックチェーン上で動かすことに注目したプラットフォームです。ブロックチェーンの対改竄性に着目すると暗号通貨の取引以外にも権利関係の移動をブロックに書き込むことでもっと汎用性のある仕組みができるのではないかという意向です、つまりアカウント指向型のプラットフォームと言えます。
スマートコントラクトとは契約情報(権利の証明や権利の移動)を自動的にブロックチェーン上に書き込むアプリケーションです。
不透明性のあるデータに関してトレーサビリティを担保するブロックチェーン技術がもっと多様なシステムに取り入れられる世の中になっていくことが楽しみですね。
参考記事
おわりに
実はビットコインのやり取りをしたことがありませんが、普段何気なくテストネットでETHやMATICのやり取りをする際にポンポンとウォレットアドレスを使っていたので今一度理解を進めようと今回記事を書いてみました。前回書いたECDSAの内容も出てきたので徐々にブロックチェーンに関わる処理内容を咀嚼できていればと思います。
最後までお読みいただきありがとうございました。
Discussion