内容简介:在加密货币中,私钥允许用户访问其钱包。持有私钥的人完全控制该钱包中数字货币。出于这个原因,你应该保守秘密。如果你真的想自己生成密钥,那么以安全的方式生成密钥是有意义的。在这里,我将介绍私钥,并向你展示如何使用各种加密函数生成自己的密钥。我将在Python中提供算法和代码的描述。大多数时候你没有。例如,如果你使用Coinbase或Blockchain.info等网络钱包,他们会为你创建和管理私钥。交易所也是如此。移动和桌面钱包通常也会为你生成私钥,但他们可以选择使用你自己的私钥创建钱包。
在加密货币中,私钥允许用户访问其钱包。持有私钥的人完全控制该钱包中数字货币。出于这个原因,你应该保守秘密。如果你真的想自己生成密钥,那么以安全的方式生成密钥是有意义的。在这里,我将介绍私钥,并向你展示如何使用各种加密函数生成自己的密钥。我将在 Python 中提供算法和代码的描述。
我需要生成私钥吗?
大多数时候你没有。例如,如果你使用Coinbase或Blockchain.info等网络钱包,他们会为你创建和管理私钥。交易所也是如此。
移动和桌面钱包通常也会为你生成私钥,但他们可以选择使用你自己的私钥创建钱包。
那么为什么要生成呢?以下是我的原因:
- 你想确保没有人知道密钥。
- 你只想了解有关加密和随机数生成(RNG)的更多信息。
什么是私钥?
形式上,比特币(以及许多其他加密货币)的私钥是一系列32字节。现在,有很多方法可以记录这些字节。它可以是256个1和0(32*8=256)或100个骰子所组成的字符串。它可以是二进制字符串,Base64字符串,WIF密钥,助记符短语,或最后是十六进制字符串。出于我们的目的,我们将使用64个字符长的十六进制字符串。
为什么正好是32字节?好问题!你可以看到,要从私有密钥创建公钥,比特币使用 ECDSA
或椭圆曲线数字签名算法。更具体地说,它使用一个称为 secp256k1
的特定曲线。
现在,该曲线具有256位的量级,以256位作为输入,并输出256位整数。256位正好是32个字节。因此,换句话说,我们需要32字节的数据来提供给这种曲线算法。
私钥还有一个额外的要求。因为我们使用ECDSA,所以关键应该是正数,并且应该小于曲线的顺序。secp256k1的顺序是 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
,它非常大:几乎任何32字节的数字都会比它小。
简单粗暴的方法
那么,我们如何生成一个32字节的整数? 首先想到的是只使用你选择的语言的RNG库。Python甚至提供了一种生成足够位的友好方式:
import random bits = random.getrandbits(256) # 30848827712021293731208415302456569301499384654877289245795786476741155372082 bits_hex = hex(bits) # 0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32 private_key = bits_hex[2:] # 4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32
看起来很好,但实际上,它不是。你看,普通的RNG库不适用于加密,因为它们不是很安全。它们根据种子生成数字,默认情况下,种子是当前时间。这样,如果你大致知道我上面生成的那些位,你需要做的就是暴力破解一些变种。
生成私钥时,你希望非常安全。请记住,如果有人学习私钥,他们可以轻松地从相应的钱包中窃取所有硬币,而你没有机会将其取回。
所以让我们尝试更安全地做到这一点。
密码学上强大的RNG
除了标准的RNG方法,编程语言通常还提供专门用于加密操作的RNG。这种方法通常更加安全,因为它直接从操作系统中提取熵。这种RNG的结果很难再现。你不能通过知道生成时间或种子来做到这一点,因为没有种子。好吧,至少用户不输入种子;相反,它是由程序创建的。
在Python中,密码强的RNG在 secrets
模块中实现。让我们修改上面的代码,使私钥生成安全!
import secrets bits = secrets.randbits(256) # 46518555179467323509970270980993648640987722172281263586388328188640792550961 bits_hex = hex(bits) # 0x66d891b5ed7f51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31 private_key = bits_hex[2:] # 66d891b5ed7f51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31
这是惊人的。我敢打赌,即使访问我的电脑,你也无法重现这一点。但我们可以更深入了吗?
专业的网站
有些网站会为你生成随机数。我们在这里只考虑两个。一个是random.org ,一个众所周知的通用随机数发生器。另一个是bitaddress.org ,专门用于比特币私钥生成。
random.org可以帮助我们生成密钥吗? 当然,因为他们有生成随机字节的服务 。但是这里出现了两个问题。Random.org声称是一个真正的随机发生器,但你能相信吗? 你能确定它确实是随机的吗? 你能确定所有者不记录所有代的结果,特别是那些看起来像私钥的结果吗? 答案取决于你。哦,你不能在本地运行它,这是一个额外的问题。此方法不是100%安全。
现在,bitaddress.org是一个完全不同的故事。它是开源的,所以你可以看到它的内部代码。它是客户端,因此即使没有Internet连接,你也可以下载并在本地运行它。
那么它是怎样工作的? 它使用你——是的,你自己——作为熵的来源。它会要求你移动鼠标或按随机键。你做得足够长,使得重现结果变得不可行。
你是否有兴趣了解bitaddress.org的工作原理?出于学习目的,我们将查看其代码并尝试在Python中重现它。
快速说明:bitaddress.org为你提供压缩WIF格式的私钥,该格式接近我们之前讨论过的WIF格式。出于我们的目的,我们将使算法返回一个十六进制字符串,以便我们以后可以使用它来生成公钥。
Bitaddress:具体细节
Bitaddress以两种形式创建熵:通过鼠标移动和按键压力。我们将讨论两者,但我们将重点关注按键,因为很难在Python lib中实现鼠标跟踪。我们希望最终用户在我们有足够的熵之前键入按钮,然后我们将生成一个密钥。
Bitaddress做了三件事。它初始化字节数组,试图从你的计算机获得尽可能多的熵,它用用户输入填充数组,然后生成一个私钥。
Bitaddress使用256字节数组来存储熵。这个数组是循环重写的,所以当第一次填充数组时,指针变为零,并且填充过程再次开始。
程序从window.crypto启动一个256字节的数组。然后,它写入时间戳以获得额外的4个字节的熵。最后,它获取的数据包括屏幕大小,时区,浏览器插件信息,区域设置等。这给了它另外6个字节。
初始化之后,程序不断等待用户输入以重写初始字节。当用户移动光标时,程序会写入光标的位置。当用户按下按钮时,程序会写入按下的按钮的字符代码。
最后,bitaddress使用累积的熵来生成私钥。它需要生成32个字节。对于此任务,bitaddress使用名为ARC4的RNG算法。程序用当前时间初始化ARC4并收集熵,然后逐个获取32次字节。
这完全是对程序运作方式的过度简化,但我希望你能得到这个想法。你可以在 Github 上详细查看算法。
自己动手吧
为了我们的目的,我们将构建一个更简单的bitaddress版本。首先,我们不会收集有关用户机器和位置的数据。其次,我们将仅通过文本输入熵,因为使用Python脚本持续接收鼠标位置非常具有挑战性(如果你想这样做,请检查 PyAutoGUI )。
这将我们带到了我们的生成器库的正式规范。首先,它将使用加密RNG初始化一个字节数组,然后它将填充时间戳,最后它将填充用户创建的字符串。种子池填满后,库将让开发人员创建一个密钥。实际上,他们将能够创建任意数量的私钥,所有私钥都由收集的熵保护。
初始化池
这里我们从加密RNG和时间戳中放入一些字节。 __seed_int
和 __seed_byte
是两个将熵插入池数组的辅助方法。请注意,我们使用 secrets
。
def __init_pool(self): for i in range(self.POOL_SIZE): random_byte = secrets.randbits(8) self.__seed_byte(random_byte) time_int = int(time.time()) self.__seed_int(time_int) def __seed_int(self, n): self.__seed_byte(n) self.__seed_byte(n >> 8) self.__seed_byte(n >> 16) self.__seed_byte(n >> 24) def __seed_byte(self, n): self.pool[self.pool_pointer] ^= n & 255 self.pool_pointer += 1 if self.pool_pointer >= self.POOL_SIZE: self.pool_pointer = 0
输入种子
这里我们首先放置一个时间戳,然后输入字符串。
def seed_input(self, str_input): time_int = int(time.time()) self.__seed_int(time_int) for char in str_input: char_code = ord(char) self.__seed_byte(char_code)
生成私钥
这部分可能看起来很难,但实际上非常简单。
首先,我们需要使用我们的池生成32字节的数字。不幸的是,我们不能只创建自己的 random
对象,只能用于密钥生成。相反,有一个共享对象,由在一个脚本中运行的任何代码使用。
这对我们意味着什么?
这意味着在每个时刻,代码中的任何地方,一个简单的 random.seed(0)
都可以破坏我们收集的所有熵。我们不希望这样。值得庆幸的是,Python提供了 getstate
和 setstate
方法。因此,为了在每次生成密钥时保存我们的熵,我们记住我们停下来的状态,并在下次我们想要创建密钥时设置它。
其次,我们只确保我们的键在范围内(1, CURVE_ORDER
)。这是所有ECDSA私钥的要求。 CURVE_ORDER
是secp256k1曲线的顺序,它是 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
。
最后,为方便起见,我们转换为十六进制,并剥离 '0x'
部分。
def generate_key(self): big_int = self.__generate_big_int() big_int = big_int % (self.CURVE_ORDER — 1) # key < curve order big_int = big_int + 1 # key > 0 key = hex(big_int)[2:] return key def __generate_big_int(self): if self.prng_state is None: seed = int.from_bytes(self.pool, byteorder=’big’, signed=False) random.seed(seed) self.prng_state = random.getstate() random.setstate(self.prng_state) big_int = random.getrandbits(self.KEY_BYTES * 8) self.prng_state = random.getstate() return big_int
行动
我们试着使用这个库。实际上,它非常简单:你可以使用三行代码生成私钥!
kg = KeyGenerator() kg.seed_input(‘Truly random string. I rolled a dice and got 4.’) kg.generate_key() # 60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2
你可以自己看看。密钥是随机的,完全有效。而且,每次运行此代码时,都会得到不同的结果。
结论
如你所见,有很多方法可以生成私钥。它们的简单性和安全性不同。
生成私钥只是第一步。下一步是提取可用于接收付款的公钥和钱包地址。
如果你想使用代码,我将它发布到这个 Github存储库 。
======================================================================
如果你想学习区块链并在Blockchain Technologies建立职业生涯,那么请查看我们分享的一些以太坊、比特币、EOS、Fabric等区块链相关的交互式在线编程实战教程:
- java以太坊开发教程,主要是针对 java 和android程序员进行区块链以太坊开发的web3j详解。
- python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
- php以太坊,主要是介绍使用 php 进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
- 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
- 以太坊开发进阶教程,主要是介绍使用node.js、 mongodb 、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
- ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。
- C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
- java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
- php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
- c#比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。
- EOS入门教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
- 深入浅出玩转EOS钱包开发 ,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。
- Hyperledger Fabric 区块链开发详解 ,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。
- Hyperledger Fabric java 区块链开发详解 ,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。
- tendermint区块链开发详解 ,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是 go 语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是 如何用python生成自己的比特币私钥
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 实战生成对抗网络(二):生成手写数字
- 实战生成对抗网络[2]:生成手写数字
- 020.Python生成器和生成器函数
- faker生成器生成虚拟数据的Python模块
- 利用代码生成工具生成基于ABP框架的代码
- 数据生成工具 ZenData 1.4 发布,内置国家、日期、时间格式,支持文章生成
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。