比特币私钥公钥地址生成

news2024/10/6 0:30:10

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

原理

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

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

实现


#!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] + result
        n /= 58
    return result


def Base256decode(s):
    '''
    base256编码
    :param s:
    :return:
    '''
    result = 0
    for c in s:
        result = result * 256 + ord(c)
    return result


def CountLeadingChars(s, ch):
    '''
    计算一个字符串开头的字符的次数
    比如:  CountLeadingChars('000001234', '0')  结果是5
    :param s:字符串
    :param ch:字符
    :return:次数
    '''
    count = 0
    for c in s:
        if c == ch:
            count += 1
        else:
            break
    return count


def Base58CheckEncode(version, payload):
    '''

    :param version: 版本前缀  , 用于区分主网 和 测试网络
    :param payload:
    :return:
    '''
    s = chr(version) + payload
    checksum = hashlib.sha256(hashlib.sha256(s).digest()).digest()[0:4]  #两次sha256, 区前4字节作为校验和
    result = s + checksum
    leadingZeros = 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_key
    return ('\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_key
    try:
        # 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; 如果是偶数, 前缀是 02
            prefix = '03'
        else:
            prefix = '02'
        return prefix + point_x
    except:
        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 mainnet
    return Base58CheckEncode(0x00, ripemd160.digest())  #00  p2pkh  mainnet




def 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 privKey


def 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1817986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

写个代码扫描插件,再也不怕 log4j 等问题

引言 关于静态代码扫描&#xff0c;大家想必都非常熟悉了&#xff0c;比如 lint、detekt 等&#xff0c;这些也都是常用的扫描工具。但随着隐私合规在国内越来越趋于常态&#xff0c;我们经常需要考虑某些危险api的调用排查等等&#xff0c;此时上述的工具往往不容易实现现有的…

PHP开发的爱情盲盒交友系统网站源码

源码介绍 PHP开发的爱情盲盒交友系统网站源码 独立后台 源码截图 源码下载 PHP开发的爱情盲盒交友系统网站源码

TCPListen客户端和TCPListen服务器

创建项目 TCPListen服务器 public Form1() {InitializeComponent();//TcpListener 搭建tcp服务器的类&#xff0c;基于socket套接字通信的//1创建服务器对象TcpListener server new TcpListener(IPAddress.Parse("192.168.107.83"), 3000);//2 开启服务器 设置最大…

Kali Linux 2022.2 发布,包含 10 个新工具和WSL 改进

Offensive Security发布了Kali Linux 2022.2&#xff0c;这是2022年的第二个版本&#xff0c;具有桌面增强功能&#xff0c;有趣的愚人节屏幕保护程序&#xff0c;WSL GUI改进&#xff0c;终端调整&#xff0c;最重要的是&#xff0c;新的工具&#xff01; Kali Linux是一个Li…

Python | Leetcode Python题解之第148题排序链表

题目&#xff1a; 题解&#xff1a; class Solution:def sortList(self, head: ListNode) -> ListNode:def merge(head1: ListNode, head2: ListNode) -> ListNode:dummyHead ListNode(0)temp, temp1, temp2 dummyHead, head1, head2while temp1 and temp2:if temp1.v…

Django中使用下拉列表过滤HTML表格数据

在Django中&#xff0c;你可以使用下拉列表&#xff08;即选择框&#xff09;来过滤HTML表格中的数据。这通常涉及两个主要步骤&#xff1a;创建过滤表单和处理过滤逻辑。 创建过滤表单 首先&#xff0c;你需要创建一个表单&#xff0c;用于接收用户选择的过滤条件。这个表单可…

集合java

1.集合 ArrayList 集合和数组的优势对比&#xff1a; 长度可变 添加数据的时候不需要考虑索引&#xff0c;默认将数据添加到末尾 package com.itheima;import java.util.ArrayList;/*public boolean add(要添加的元素) | 将指定的元素追加到此集合的末尾 | | p…

E-R数据模型是什么?

概念模型是从现实世界到计算机世界转换的一个中间层次,在数据库设计的过程中它是比较关键的一步。因此,概念模型必须能够真实地反映现实世界中被管理事物的特征及其复杂的联系,即应该具有丰富的语义表达能力和直接模拟现实世界的能力,且具有直观、自然、语义丰富、易于用户…

「51媒体」媒体邀约-全国邀请媒体现场报道宣传

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 「51媒体」媒体邀约是一家专注于提供媒体传播方案和执行的服务公司&#xff0c;旨在通过一站式服务帮助企业或个人进行有效的媒体邀约和活动宣传。 「51媒体」提供的不仅仅是简单的媒体邀…

U盘文件删除如何恢复?4个实用技巧(含图文)

“我的u盘里保存了很多重要的文件&#xff0c;但是不知道为什么部分文件丢失&#xff0c;有什么方法可以帮我快速恢复u盘文件的吗&#xff1f;希望大家帮帮我&#xff01;” U盘作为我们日常存储和传输数据的重要工具&#xff0c;其数据的安全性和可恢复性尤为重要。当U盘中的文…

Vue22-v-model收集表单数据

一、效果图 二、代码 2-1、HTML代码 2-2、vue代码 1、v-model单选框的收集信息 v-model&#xff1a;默认收集的就是元素中的value值。 单选框添加默认值&#xff1a; 2、v-model多选框的收集信息 ①、多个选择的多选 注意&#xff1a; 此处的hobby要是数组&#xff01;&…

白酒:茅台镇白酒的品鉴会与文化交流活动

茅台镇&#xff0c;这个位于中国贵州省的小镇&#xff0c;因其与众不同的自然环境和杰出的酿酒工艺而成为世界著名的白酒产区。云仓酒庄豪迈白酒作为茅台镇的品牌&#xff0c;积极参与各种品鉴会和文化交流活动&#xff0c;向世界展示了中国白酒的魅力和文化底蕴。 近年来&…

华为云CodeArts API:API管理一体化平台 5月新特性上线啦!

CodeArts API是华为云API全生命周期管理一体化解决方案平台&#xff0c;支持开发者高效实现API设计、API开发、API测试、API托管、API运维、API变现的一站式体验。 通过以API契约为锚点&#xff0c;CodeArts API保证API各阶段数据高度一致&#xff0c;为开发者提供友好易用的A…

低功耗,大算力!最适合大模型的AI芯片是它?

在如今AI技术飞速发展的时代&#xff0c;AI加速芯片已经成为了大模型时代必不可少的核心组件。从CPU到GPU&#xff0c;再到TPU和NPU&#xff0c;各种芯片不断涌现&#xff0c;但都面临着能耗和算力的平衡问题。那么&#xff0c;有没有一种AI芯片能够同时满足低功耗和高算力的需…

(el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程

Ⅰ、Element-plus 提供的Select选择器组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供Select组件情况&#xff1a; 其一、Element-ui 自提供的Select代码情况为(示例的代码)&#xff1a; // Element-plus 提供的组件代码: <template><div class"f…

前端JS必用工具【js-tool-big-box】学习,下载大文件(纯下载功能版)

这一小节呢&#xff0c;我们说一下 js-tool-big-box 工具库&#xff0c;下载文件的用法。这一小节说的是纯下载版本。 意思就是我们在前端项目开发中&#xff0c;下载功能嘛&#xff0c;无论你发送fetch请求&#xff0c;还是axios请求&#xff0c;你总得发送一下请求&#xff0…

车载网络安全指南 概述(一)

返回总目录->返回总目录<- 目录 前言 参考文档 术语 前言 汽车电子系统网络安全指南给出汽车电子系统网络安全活动框架,以及在此框架下的汽车电子系统网络安全活动、组织管理和支持保障等方面的建议。 汽车电子系统网络安全指南适用于指导整车厂、零部件供应商、软…

自定义函数命名规范

自定义函数命名规范 正文自定义函数名称不能与内置函数名称一致自定义函数名称不能与文件名称一致 正文 在 Lumerical 中&#xff0c;对于自定义函数名称&#xff0c;也有必须要遵守的规则。这里简单记录一下。 自定义函数名称不能与内置函数名称一致 比如&#xff0c;内置函…

深度神经网络——语音识别技术的探索与应用

概述 论文地址&#xff1a;https://arxiv.org/pdf/2402.19443.pdf 使用深度学习的语音识别技术已取得重大进展。这使得语音识别系统更加准确。然而&#xff0c;这项技术非常复杂&#xff0c;很难理解哪些信息用于何处。因此&#xff0c;本文提出了一种识别语音识别系统中哪些信…

Vue 项目开启 gzip

1. 压缩方式&#xff1a; 在 Nginx 开启压缩&#xff1a;当浏览器发起请求时&#xff0c;服务端对传输资源进行实时压缩&#xff0c;然后返回给浏览器&#xff1b;前端配置打包压缩并在服务端加上支持 gizp 的配置&#xff1a;当浏览器请求时&#xff0c;服务端直接将压缩资源…