ブロックチェーンについて復習します
これを読めばサルでもわかるかも?
2119 views
「アドレス」は、仮想通貨を送る・受け取る際に利用するものや。
「仮想通貨を送る・受け取る」性質上、アドレスは多くの人が目にするわ。
ただ、個人と紐づいているプライバシーの高いものでもあるわ。
要するに
この二つを満たす必要があるわけやな
「アドレス」は「秘密鍵」から作られているわ。
「秘密鍵」から「アドレス」が作られるには下図手順を踏むんやで
[秘密鍵]
[公開鍵]
[アドレス]
秘密鍵の本質は乱数や。乱数はランダムに生成される数や。
乱数が本当にランダムかは、非常に重要やで。規則性があると悪意のある第三者に秘密鍵が悪用されるわ。
[入力]
import os
import binascii
#32バイトの乱数の生成
private_key = os.urandom(32)
print(private_key)
#バイナリデータを16進数に変換する(これはわかりやすくするためにやっている)
print(binascii.hexlify(private_key))
[出力]
b'V!-Z\xfb\x11\xb6\x9c\xc9\xc5s\\\x9a\xeeU\xf4\xa4\xfc8\x9b\x03\xbeD\xab\xf9eD\x93\xaa\x19&\x1a'
b'56212d5afb11b69cc9c5735c9aee55f4a4fc389b03be44abf9654493aa19261a'
[入力]
import ecdsa
import os
import binascii
#秘密鍵生成
private_key = os.urandom(32)
#公開鍵の生成
public_key = ecdsa.SigningKey.from_string(private_key,curve=ecdsa.SECP256k1).verifying_key.to_string()
print(binascii.hexlify(private_key))
print(binascii.hexlify(public_key))
[出力]
#毎回異なる値が出力される
b'8ea97805a01622ed58d48e0618ede12bb78882570e1008ae0544a89fa76db8a0'
b'0f23ae30c79de5587395d0c66b7533e3648e08b5aab4e8fe87001a5470bdc035b68ef004efd8f2b342d28abf2219a3e9d3aec26e6d9f15aef5c1afb0e47ce906'
===細かい説明は今度するわ...===
非圧縮公開鍵は前節で導き出した公開鍵に「プレフィックス」として「04」を付加したもの。
「プレフィックス」とは、接頭辞のこと。特定の意味を持たせる
公開鍵「楕円曲線」で作られている。よって座標を求めることができる。
圧縮公開鍵の場合、座標Yの値によってプレフィックスを変更する。
[入力]
import ecdsa
import os
import binascii
#秘密鍵生成
private_key = os.urandom(32)
#公開鍵の生成
public_key = ecdsa.SigningKey.from_string(private_key,curve=ecdsa.SECP256k1).verifying_key.to_string()
#Y座標を取得(32から取得。)
public_key_y = int.from_bytes(public_key[32:],"big")
#圧縮公開鍵を生成(32まで取得)
if public_key_y %2 == 0:
public_key_compressed = b"\x02"+public_key[:32]
else:
public_key_compressed = b"\x03"+public_key[:32]
#実行するたび値が変わる
print(binascii.hexlify(public_key))
print(binascii.hexlify(public_key_compressed))
[出力]
b'6b57dab2663217d95fb73a14a92b758cc087f84f099cca50fdcdaeb444985b6ed41bebfac760d8f3da6ffafd09a7ccd7d1f3872369152cea0402f08a0972895c'
b'026b57dab2663217d95fb73a14a92b758cc087f84f099cca50fdcdaeb444985b6e'
ここまで予測されないように秘密鍵を生成し、逆算不可な「公開鍵」を生成した。
ここからは、エンコードして可読性を高めて、誤読を防ぐ工夫をするんやで
具体的には「RIPEMD-160」で文字量を減らし「Base58Check」でエンコードする
「Base58」は人が見て間違えやすい文字を排除するエンコード方式や。
例えば、Oと0とかやな。ほかには以下の文字があげられるわ。
公開鍵からアドレスを生成する際はチェックサムを使用した「Base58Check」を用いるわ。
「チェックサム」ってのはデータが間違っていないか確認する手法や。
ここでのチェックサムは、公開鍵のハッシュ値とその先頭にバージョンバイトをつなげたものから
1. SHA-256で2回ハッシュ化する
2. その先頭4バイトを利用する
プロセスは以下の通りや。
バージョンバイトってのは、生成するアドレスがどのようなタイプのアドレスかを示す。
16進数の情報やで。
別名:Version Prefix とも呼ぶわ。
代表的なバージョンバイトは下の通りや
バージョンバイト | 意味 | エンコード後 |
---|---|---|
0x00 | 公開鍵ハッシュ | 1 |
0x05 | スクリプトハッシュ | 3 |
0x08 | 秘密鍵WIF形式 | 5 |
0x0488B21E | BIP32拡張公開鍵 | xpub |
公開鍵からアドレスを生成するプロセスは以下の通りやで
[入力]
import ecdsa
import os
import base58
import hashlib
#秘密鍵生成
private_key = os.urandom(32)
#公開鍵の生成
public_key = ecdsa.SigningKey.from_string(private_key,curve=ecdsa.SECP256k1).verifying_key.to_string()
#非圧縮公開鍵
prefix_and_pubkey = b"\x04"+ public_key
#hash160を作成
intermediate = hashlib.sha256(prefix_and_pubkey).digest()
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(intermediate)
hash160 = ripemd160.digest()
#ハッシュ160 + バージョンプレフィックス
prefix_and_hash160 = b"\x00" + hash160
#hashlib.256を入れる
double_hash = hashlib.sha256(hashlib.sha256(prefix_and_hash160).digest()).digest()
#チェックサム
check_sum = double_hash[:4]
pre_address = prefix_and_hash160 + check_sum
#base58でエンコード
address = base58.b58encode(pre_address)
print(address)
[出力]
#実行する毎に変更する
b'1PwungCcLKepQCQZZB73hEc6PboB6GjFPr'
Page 6 of 9.
owl
駆け出しエンジニア
だいたいweb系をかじってる
最近ちょとブロックチェーンに興味出てきた