密钥和地址
BTC密钥和地址之间的转换如下:
$ pip install base58
$ pip install ecdsa
import hashlib
import base58
import ecdsa
G = ecdsa.SECP256k1.generator
BYTES = lambda number, length: number.to_bytes(length, byteorder='big')
BASE58CHECK = base58.b58encode_check
RIPEMD160 = lambda x: hashlib.new('ripemd160', x).digest()
SHA256 = lambda x: hashlib.sha256(x).digest()
输入 |
参数 |
输出 |
函数 |
私钥(整数) |
k |
私钥(二进制) |
bin(k) |
私钥(整数) |
k |
私钥(十六进制) |
hex(k) |
私钥(整数) |
k |
私钥(WIF) |
BASE58CHECK(BYTES((0x80 << 256 | k), 33)) |
私钥(整数) |
k |
私钥(WIF compressed) |
BASE58CHECK(BYTES(((0x80 << 256 | k) << 8 | 0x01), 34)) |
私钥(整数) |
k(小写) |
公钥(坐标) |
K = k * G |
公钥(坐标) |
K |
公钥(整数) |
((0x04 << 256) | K.x()) << 256 | K.y() |
公钥(坐标) |
K |
公钥(整数 压缩) |
((0x02 if K.y() % 2 == 0 else 0x03) << 256) | K.x() |
公钥(整数) |
Pub |
地址 |
BASE58CHECK(b'\x00' + RIPEMD160(SHA256(BYTES(Pub, 65)))) |
公钥(整数 压缩) |
Pub |
地址 |
BASE58CHECK(b'\x00' + RIPEMD160(SHA256(BYTES(Pub, 33)))) |
示例
main.py
import hashlib
import base58
import ecdsa
G = ecdsa.SECP256k1.generator
assert G.x() == \
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
assert G.y() == \
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
BYTES = lambda number, length: number.to_bytes(length, byteorder='big')
BASE58CHECK = base58.b58encode_check
RIPEMD160 = lambda x: hashlib.new('ripemd160', x).digest()
SHA256 = lambda x: hashlib.sha256(x).digest()
k = 0x1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd
assert hex(k) == \
'0x1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd'
assert (0x80 << 256 | k) == \
0x801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd
assert BASE58CHECK(BYTES((0x80 << 256 | k), 33)) == \
b'5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn'
assert ((0x80 << 256 | k) << 8 | 0x01) == \
0x801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd01
assert BASE58CHECK(BYTES(((0x80 << 256 | k) << 8 | 0x01), 34)) == \
b'KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ'
K = k * G
Pub = ((0x04 << 256) | K.x()) << 256 | K.y()
assert Pub == \
0x4f028892bad7ed57d2fb57bf33081d5cfcf6f9ed3d3d7f159c2e2fff579dc341a07cf33da18bd734c600b96a72bbc4749d5141c90ec8ac328ae52ddfe2e505bdb
Pub_compressed = ((0x02 if K.y() % 2 == 0 else 0x03) << 256) | K.x()
assert Pub_compressed == \
0x3f028892bad7ed57d2fb57bf33081d5cfcf6f9ed3d3d7f159c2e2fff579dc341a
assert BASE58CHECK(b'\x00' + RIPEMD160(SHA256(BYTES(Pub, 65)))) == \
b'1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x'
assert BASE58CHECK(b'\x00' + RIPEMD160(SHA256(BYTES(Pub_compressed, 33)))) == \
b'1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy'