您的位置:首页 > 财经 > 金融 > 比特币私钥公钥地址生成

比特币私钥公钥地址生成

2024/7/3 11:00:11 来源:https://blog.csdn.net/qq_67479387/article/details/139609832  浏览:    关键词:比特币私钥公钥地址生成

比特币私钥公钥地址生成算法

原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实现


#!coding:utf8#author:yqq
#date:2019/3/4 0004 14:35
#description:  比特币地址生成算法import hashlib
import ecdsa
import os#2019-05-15  添加私钥限制范围
g_b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'#g_nMaxPrivKey = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 - 0x423423843  #私钥最大值 (差值是自定义的)
#g_nMinPrivKey = 0x0000000000000000000000000000000000000000000000000000000000000001 + 0x324389329  #私钥最小值 (增值是自定义的)#2019-11-12 根据官方定义修改  有限域
# http://www.secg.org/sec2-v2.pdf#page=9&zoom=100,0,249
# 关于 有限域的定义 请参考
# 0xEFFFFFC2F = 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1
g_nFactor = 0xEFFFFFC2F + 0x23492397 #增值自定义
g_nMaxPrivKey = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 - g_nFactor #私钥最大值 (差值是自定义的)
g_nMinPrivKey = 0x0000000000000000000000000000000000000000000000000000000000000001 + g_nFactor #私钥最小值 (增值是自定义的)def Base58encode(n):'''base58编码:param n: 需要编码的数:return: 编码后的'''result = ''while n > 0:result = g_b58[n % 58] + resultn /= 58return resultdef Base256decode(s):'''base256编码:param s::return:'''result = 0for c in s:result = result * 256 + ord(c)return resultdef CountLeadingChars(s, ch):'''计算一个字符串开头的字符的次数比如:  CountLeadingChars('000001234', '0')  结果是5:param s:字符串:param ch:字符:return:次数'''count = 0for c in s:if c == ch:count += 1else:breakreturn countdef Base58CheckEncode(version, payload):''':param version: 版本前缀  , 用于区分主网 和 测试网络:param payload::return:'''s = chr(version) + payloadchecksum = hashlib.sha256(hashlib.sha256(s).digest()).digest()[0:4]  #两次sha256, 区前4字节作为校验和result = s + checksumleadingZeros = CountLeadingChars(result, '\0')return '1' * leadingZeros + Base58encode(Base256decode(result))def PrivKeyToPubKey(privKey):'''私钥-->公钥:param privKey: 共65个字节:  0x04   +  x的坐标  +   y的坐标:return:'''sk = ecdsa.SigningKey.from_string(privKey.decode('hex'), curve=ecdsa.SECP256k1)# vk = sk.verifying_keyreturn ('\04' + sk.verifying_key.to_string()).encode('hex')def PrivKeyToPubKeyCompress(privKey):'''私钥-->公钥  压缩格式公钥:param privKey:  ( 如果是奇数,前缀是 03; 如果是偶数, 前缀是 02)   +  x轴坐标:return:'''sk = ecdsa.SigningKey.from_string(privKey.decode('hex'), curve=ecdsa.SECP256k1)# vk = sk.verifying_keytry:# print(sk.verifying_key.to_string().encode('hex'))point_x = sk.verifying_key.to_string().encode('hex')[     : 32*2] #获取点的 x 轴坐标point_y = sk.verifying_key.to_string().encode('hex')[32*2 :     ]  #获取点的 y 轴坐标# print("point_x:", point_x)if (long(point_y, 16) & 1) == 1:  # 如果是奇数,前缀是 03; 如果是偶数, 前缀是 02prefix = '03'else:prefix = '02'return prefix + point_xexcept:raise("array overindex")pass#https://en.bitcoin.it/wiki/List_of_address_prefixes
def PubKeyToAddr(privKey, isTestnet = False):'''公钥-->地址:param privKey:私钥:param isTestnet:是否是测试网络:return:地址'''ripemd160 = hashlib.new('ripemd160')ripemd160.update(hashlib.sha256(privKey.decode('hex')).digest())if isTestnet:return Base58CheckEncode(0x6F, ripemd160.digest())  #0x6F  p2pkh  testnet# return base58CheckEncode(0x05, ripemd160.digest())  #05  p2sh mainnetreturn Base58CheckEncode(0x00, ripemd160.digest())  #00  p2pkh  mainnetdef PrivKeyToWIF(privKey, isTestnet = False):'''将私钥转为 WIF格式 , 用于比特币钱包导入:param privKey: 私钥(16进制字符串):return: WIF格式的私钥'''if isTestnet:# return Base58CheckEncode(0xEF, privKey.decode('hex') + '\01') #0xEF 测试网络          fix bug: 2019-04-03 yqq 01是多余的, 只有是压缩的格式的时候,才需要加return Base58CheckEncode(0xEF, privKey.decode('hex') ) #0xEF 测试网络# return Base58CheckEncode(0x80, privKey.decode('hex') + '\01') #0x80 主网return Base58CheckEncode(0x80, privKey.decode('hex') ) #0x80 主网def PrivKeyToWIFCompress(privKey, isTestnet = False):'''压缩格式将私钥转为 WIF格式 , 用于比特币钱包导入:param privKey: 私钥(16进制字符串):return: WIF格式的私钥'''if isTestnet:return Base58CheckEncode(0xEF, privKey.decode('hex') + '\01') #0xEF 测试网络return Base58CheckEncode(0x80, privKey.decode('hex') + '\01') #0x80 主网def GenPrivKey():'''生成私钥, 使用 os.urandom (底层使用了操作系统的随机函数接口, 取决于CPU的性能,各种的硬件的数据指标):return:私钥(16进制编码)'''#2019-05-15 添加私钥范围限制while True:privKey = os.urandom(32).encode('hex')    #生成 256位 私钥if  g_nMinPrivKey < int(privKey, 16) <   g_nMaxPrivKey:return privKeydef GenAddr(isTestnet=False):'''此函数用于C++调用,:param isTestnet: 是否是测试网络:return:  (私钥, 公钥, 地址)'''privKey = GenPrivKey()# print("privkey : " + privKey)privKeyWIF =  PrivKeyToWIF(privKey, isTestnet)# print("privkey WIF:" + PrivKeyToWIF(privKey, isTestnet))pubKey = PrivKeyToPubKey(privKey)# print("pubkey : " + pubKey)addr = PubKeyToAddr(pubKey, isTestnet)# print("addr : " + addr)return str(privKeyWIF), str(pubKey), str(addr)def GenAddrCompress(isTestnet=False):'''此函数用于C++调用,:param isTestnet: 是否是测试网络:param isCompress: 是否压缩:return:  (私钥, 公钥, 地址)'''privKey = GenPrivKey()# print("privkey : " + privKey)privKeyWIF =  PrivKeyToWIFCompress(privKey, isTestnet)# print("privkey WIF:" + PrivKeyToWIF(privKey, isTestnet))pubKey = PrivKeyToPubKeyCompress(privKey)# print("pubkey : " + pubKey)addr = PubKeyToAddr(pubKey, isTestnet)# print("addr : " + addr)return str(privKeyWIF), str(pubKey), str(addr)def GenMultiAddr(nAddrCount = 1, isTestnet=True):'''生成多个地址:param nAddrCount::param isTestnet::return:'''# return [("1111", "2222", "3333"), ("4444", "55555", "66666")]# return [1, 2, 3, 4]# return ["1111", "2222", "3333", "4444"]lstRet = []for i in range(nAddrCount):lstRet.append(GenAddrCompress(isTestnet))return lstRet#
def good():isTestnet = True# private_key = GenPrivKey()private_key = '95b51ad564bd26811aeafc06ebe64643d2a50f82aa4901e714ba4be635ed9a57'print("privkey : " + private_key)print("privkey WIF:" + PrivKeyToWIF(private_key, isTestnet))pubKey = PrivKeyToPubKey(private_key)print("pubkey : " + pubKey)addr = PubKeyToAddr( pubKey , isTestnet)print("addr : " + addr)print("-----------------------------")print("privkey WIF compress:" + PrivKeyToWIFCompress(private_key, isTestnet))pubKey = PrivKeyToPubKeyCompress(private_key)print("pubkey  compress : " + pubKey)addr = PubKeyToAddr( pubKey , isTestnet)print("addr  compress: " + addr)
#
#
# def main():
#     good()
#     for i in range(1):
#         print(GenAddr(True))# if __name__ == '__main__':
#
#     main()

关于地址压缩

参考链接: https://bitcoin.stackexchange.com/questions/3059/what-is-a-compressed-bitcoin-key

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com