前情回顾
BTC的私钥
我们一直在说要保存好 你的私钥,其实呢,BTC的私钥就是 椭圆曲线加密算法(ECC,非对称加密)一组密钥中的私钥。
BTC中的椭圆曲线加密算法
通用的椭圆曲线加密算法方程为:
y 2 = x 3 + a x + b y^2 = x^3 + ax + b y2=x3+ax+b
BTC使用的是 secp256k1
型的椭圆曲线加密算法,如下:
y 2 = x 3 + 7 y^2 = x^3 + 7 y2=x3+7
生成一个例子
还记得我们前面讲到的 助记词 部分吗?那里有生成私钥的代码,下面就是我们使用代码生成的一组公私钥信息。
{
"cryptocurrency": "Bitcoin",
"symbol": "BTC",
"network": "mainnet",
"strength": 128,
"entropy": "410819912a17a78c8435f2983f5d6b86",
"mnemonic": "donate dolphin gold feature kidney shock awkward salad oblige wife foot arrive",
"language": "english",
"passphrase": null,
"seed": "0d62a738e4f9202b05f9e8dc719db73eb6917de4c9fd3c1074ea8941ba32687c2ce716088b503fbd0e1fd91625462518778e669efc764b9678a83a0f6c5a9381",
"root_xprivate_key": "xprv9s21ZrQH143K4NBNEYZpVcmj6G7revDdJAVqLzRXLDW6ZUF867YKWx7zaiV3fSigfaCP28zDrcxNTCy2e34MZmon8bnySpDKdwEZWrPVZJF",
"root_xpublic_key": "xpub661MyMwAqRbcGrFqLa6prkiTeHxM4NwUfPRS9Nq8tZ35SGaGdera4kSUS16NgiGMzUc5cPx7joK1tgVjEdzDig5pnCYKMRyrcnNf9zmuMGx",
"xprivate_key": "xprvA43m4nyQUEvt7rntJfpWxZwgK1YHwmVQtuU8jy4wSPSVzBNuwgzMJmSRfqZqwkyWWgF5BxQ1Aow4wzNE7bUAPicVL68HjefowJ4zriorYmS",
"xpublic_key": "xpub6H37UJWJJcVBLLsMQhMXKhtQs3NnMEDGG8PjYMUYziyUryi4VEJbrZkuX6WSSNdLCFG5Yt4EhPWYNzwNitwThEry62k9zdCWnoFXrXnbpJy",
"uncompressed": "21e01e151e679102849fd06f00704c79bdca7c18996f05228127996d15f63977cd17c815ae5bec74d018fb4fff53a1f7a69a1dff9b871cf8e13fa03f5428e000", // 这个是未压缩的公钥
"compressed": "0221e01e151e679102849fd06f00704c79bdca7c18996f05228127996d15f63977",
"chain_code": "25bb20ef652715dac08041456ca635de5e1f2f914425bd1ea22722a44ff577cb",
"private_key": "2d9e386e9d7d3f3d128f344c9729d29bd2a27044214c789bf8574e5323b3602b", // 这个是私钥
"public_key": "0221e01e151e679102849fd06f00704c79bdca7c18996f05228127996d15f63977", // 这个是公钥
"wif": "KxkPN8DzYmZHk6WGVzzyKMUueyHAEaBXUX5H7BviqHyYRdt5KuXe",
"finger_print": "b2650ac0",
"semantic": "p2pkh",
"path": "m/44'/0'/0'/0/0",
"hash": "b2650ac0b0a48d784f7d08e3e1706a3206a3d80d",
"addresses": { // 这里是几种格式的地址
"p2pkh": "1HGGKfhbowZ4UD3HNJXFSQ1DEDADan4Z2o",
"p2sh": "3PRi5SKLobx3fDQh7H6DTwrxxLC65Ccko9",
"p2wpkh": "bc1qkfjs4s9s5jxhsnmapr37zur2xgr28kqdlxvfkx",
"p2wpkh_in_p2sh": "3PCuy8eXZsBw28ij8LckRs4aBgP8FiYJF6",
"p2wsh": "bc1q8t5lkf9jn8vr0evjec2wafzl5v3qts0g650jtq8f7r3r79q375ks9wx0ue",
"p2wsh_in_p2sh": "37FFRbiXxtSSGVrb5wSWZsXS9T8R9ydqjT"
}
}
使用Python验证上面的例子
通过16进制的私钥,计算WIF格式的私钥
通过16进制的私钥,计算出压缩格式的公钥
使用ECDSA库进行椭圆曲线加密,下面代码中有实现,这里不用图例说明了
通过压缩格式的公钥,计算BTC钱包的地址
代码实现
import ecdsa
import hashlib
import base58
# 从16进制私钥计算出压缩,非压缩的公钥
def private_key_to_public_key(private_key):
# 转换私钥为bytes
private_key_bytes = bytes.fromhex(private_key)
# 使用ECDSA库进行椭圆曲线加密
sk = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1)
# 获取公钥
vk = sk.get_verifying_key()
# 获取未压缩的公钥(64字节)
uncompressed_public_key = vk.to_string()
# 获取压缩后的公钥
compressed_public_key = vk.to_string("compressed")
return uncompressed_public_key.hex(), compressed_public_key.hex()
# 从public_key计算出BTC地址
def public_key_to_address(public_key_hex):
# 将公钥进行哈希(SHA256 和 RIPEMD160)
sha256_hash = hashlib.sha256(bytes.fromhex(public_key_hex)).digest()
ripemd160_hash = hashlib.new('ripemd160', sha256_hash).digest()
# 添加版本字节
extended_hash = b'\x00' + ripemd160_hash # 主网比特币地址版本字节为0x00
# 使用两次SHA256进行校验和计算
checksum = hashlib.sha256(hashlib.sha256(extended_hash).digest()).digest()[:4]
# 添加校验和
binary_address = extended_hash + checksum
# 使用Base58进行编码
bitcoin_address = base58.b58encode(binary_address).decode('utf-8')
return bitcoin_address
# 从16进制的私钥计算出WIF格式的私钥
def private_key_to_wif(private_key_hex):
# 添加版本字节
extended_key = b'\x80' + bytes.fromhex(private_key_hex) + b'\x01' # 主网比特币私钥版本字节为0x80, 0x01表示使用压缩公钥
# 使用两次SHA256进行校验和计算
checksum = hashlib.sha256(hashlib.sha256(extended_key).digest()).digest()[:4]
# 添加校验和
extended_key_with_checksum = extended_key + checksum
# 使用Base58进行编码
wif_key = base58.b58encode(extended_key_with_checksum).decode('utf-8')
return wif_key
# 替换下面的private_key为你的BTC私钥
private_key = "2d9e386e9d7d3f3d128f344c9729d29bd2a27044214c789bf8574e5323b3602b"
wif_private_key = private_key_to_wif(private_key)
print("输入的BTC私钥为:", private_key)
print("WIF格式的私钥:", wif_private_key)
public_key_array = private_key_to_public_key(private_key)
print("BTC公钥(未压缩,16进制表示):", public_key_array[0])
print("BTC公钥(压缩,16进制表示):", public_key_array[1])
bitcoin_address = public_key_to_address(public_key_array[1])
print("BTC address:", bitcoin_address)
输出:
输入的BTC私钥为: 2d9e386e9d7d3f3d128f344c9729d29bd2a27044214c789bf8574e5323b3602b
WIF格式的私钥: KxkPN8DzYmZHk6WGVzzyKMUueyHAEaBXUX5H7BviqHyYRdt5KuXe
BTC公钥(未压缩,16进制表示): 21e01e151e679102849fd06f00704c79bdca7c18996f05228127996d15f63977cd17c815ae5bec74d018fb4fff53a1f7a69a1dff9b871cf8e13fa03f5428e000
BTC公钥(压缩,16进制表示): 0221e01e151e679102849fd06f00704c79bdca7c18996f05228127996d15f63977
BTC address: 1HGGKfhbowZ4UD3HNJXFSQ1DEDADan4Z2o
经过对比,程序跑出的代码,和我们之前生成的一致。
最后使用区块浏览器查询我们刚刚计算出的BTC钱包地址
使用Edge浏览器的Web3钱包插件导入WIF格式的私钥
这里就不演示了,如果有问题可以私信我。
注:之前推荐的OneKey钱包导入WIF私钥有问题,建议使用欧易插件来进行导入测试。