主页 > imtoken钱包官方下载最新地址 > 区块链的第一个应用---比特币,它的(密钥、地址、钱包)

区块链的第一个应用---比特币,它的(密钥、地址、钱包)

区块链的第一应用---比特币,之 (密钥、地址、钱包)

比特币的所有权是通过数字密钥、比特币地址和数字签名建立的。数字密钥实际上并不存储在网络中,而是由用户生成并存储在称为钱包的文件或简单数据库中。存储在用户钱包中的数字密钥完全独立于比特币合约,可以由用户的钱包软件生成和管理,无需区块链或网络连接。密钥支持比特币的许多有趣功能,包括去中心化信任和控制、所有权身份验证以及基于加密证明的安全模型。

单个比特币交易需要有效的签名才能存储在区块链上。只有有效的数字密钥才能形成有效的数字签名,因此拥有比特币密钥的副本可以让您控制帐户的比特币。密钥成对出现,由公钥和私钥组成。私钥好比建行的账号,公钥好比控制账户或汇票签名的PIN码。比特币用户很少直接看到数字密钥。通常,它们存储在钱包文件中,由比特币钱包软件管理。

在比特币交易的支付过程中,发送者的私钥由它的数字指纹表示,称为比特币地址,就像汇票上的支付对象的名称(即“收款人”) )。 ”)。通常,比特币地址由私钥生成并对应于私钥。然而,并不是所有的比特币地址都是私钥;它们还可以表示其他支付对象,例如我们将在本章前面提到的脚本。通过这种方式,比特币地址将接收者可视化,使交易的目的地更加灵活,就像汇票一样:这种支付工具可以支付到个人账户、企业账户、账单支付或现金支付。比特币地址是用户经常看到的密钥的唯一表示,他们只需要告诉别人比特币地址。

在本章中,我们将介绍密钥所在的钱包。我们将看到密钥是如何形成、存储和管理的。我们将回顾公钥和私钥、地址和脚本地址的各种编码格式。最后,我们将介绍密钥的特殊用途:生成签名、证明所有权以及创建比特币虚荣地址和香棒。

4.1.1私钥加密和加密

私钥加密是在 1970 年代发明的。它是计算机和信息安全的物理基础。

自私钥加密发明以来,已经提出了一些合适的物理函数,例如素数幂和椭圆曲线加法。这些物理函数是不可逆的,这意味着在一个方向上很容易估计,但不能在相反方向上推回。基于这种物理功能的密码学使得生成数字密钥和不可伪造的数字签名成为可能。比特币使用椭圆曲线加法作为其私钥加密的底层算法。

在比特币系统中,我们使用私钥加密来创建密钥对来控制比特币的获取。密钥对由一个公钥和一个从它派生的唯一私钥组成。私钥用于接收比特币,而公钥用于在比特币支付时签署交易。

私钥和公钥之间的物理关系,这样公钥可用于为特定消息生成签名。此签名在不泄露公钥的情况下验证私钥。

在支付比特币时,比特币的当前所有者需要在交易中提交他们的私钥和签名(每笔交易的签名不同,但由相同的公钥生成)。比特币网络中的每个人都可以通过提交的私钥和签名进行验证,并确认交易是否有效,即确认付款人拥有当时正在交易的比特币的所有权。

为了方便起见,大多数比特币钱包工具将公钥和私钥作为密钥对存储在一起。但是,私钥可以从公钥估计出来,所以也可以只存储公钥。

4.1.2个公钥和私钥

一个比特币钱包包含一系列密钥对,每个密钥对包括一个公钥和一个私钥。公钥 (k) 是一个数字,通常是随机选择的。有了公钥,我们可以使用椭圆曲线加法(一种双向加密函数)形成私钥(K)。使用私钥(K),我们可以使用双向加密哈希函数生成比特币地址(A)。在本节中,我们将从生成公钥开始,描述如何使用椭圆曲线运算从公钥生成私钥,最后从私钥生成比特币地址。公钥、公钥、比特币地址的关系如右图所示。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

4.1.3 公钥

公钥只是一个随机数。对比特币地址中所有资金的控制取决于相应公钥的所有权和控制权。在比特币交易中,公钥用于生成支付比特币所需的签名,以证明资金的所有权。公钥必须永远保密,因为一旦泄露给第三方,相当于保护公钥的比特币也会屈服。公钥也必须备份,以防意外丢失,因为公钥一旦丢失就无法找回,它所保护的比特币也将永远丢失。

比特币公钥只是一个数字。您可以用硬币、铅笔和纸随机生成您的公钥:掷硬币 256 次,用纸和笔记录正反面并转换为 0 和 1,随机的 256 位二进制补码数可用作比特币钱包的公钥。这个公钥可以进一步生成私钥。

从随机数生成公钥

生成密钥的第一步也是最重要的一步是找到足够安全的熵源,即随机源。生成比特币公钥本质上与“选择 1 到 2256 之间的数字”相同。数字如何选择并不重要,只要选择的结果是不可预测或不可重复的。比特币软件使用操作系统底层的随机数生成器来形成 256 位的熵(随机性)。一般来说,操作系统随机数生成器是由人工随机源初始化的,也可能是通过连续扭动键盘几秒钟来初始化。对于真正的偏执狂,请使用掷骰子并用笔和纸记录下来。

更准确地说,公钥可以是 1 到 n-1 之间的任意数字,其中 n 是一个常数(n=1.158*1077,略大于 2256),并且由比特币使用的椭圆曲线的阶数定义(参见4.1.5 Elliptic Curve Cryptography Explained)。要生成这样的公钥,我们随机选择一个 256 位的 ,并检查它是否大于n - 1。从编程的角度来看,这通常是通过从加密安全的随机源中取出一长串随机字节并使用SHA256哈希算法来完成的,这样就可以很容易地得到一个256位的数字形成。如果运算结果大于n-1,我们就有一个合适的公钥。否则,我们用另一个随机数重复。

本书强烈建议读者不要使用自己的代码或使用编程语言内置的简单随机数生成器来获取随机数。我们建议读者使用加密安全的伪随机数生成器 (CSPRNG),并且必须具有来自具有足够熵的源的种子的随机数。使用随机数生成器库时,请仔细阅读其文档以确保其加密安全。正确实施 CSPRNG 是密钥安全的关键。

以下是随机生成的公钥(k),用16位补码格式表示(256位二进制补码,显示为64位16位补码,每个16位补码4位):

1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD

比特币公钥空间的大小是 2256,这是一个非常大的数字。如果用 10 的补码表示,大约是 1077,可见宇宙被认为只富含 1080 个原子。

要使用比特币核心客户端(参见第 3 章)生成新密钥,请使用 getnewaddress 命令。出于安全考虑考虑到命令运行后,只显示生成的私钥,不显示公钥。如果你想让 bitcoind 显示公钥,你可以使用 dumpprivkey 命令。 dumpprivkey 命令将以 Base58 校准和编码格式显示公钥。这些公钥格式称为钱包导出格式(WIF,WalletImportFormat),在“私钥的格式”一节中有详细说明。以下是使用这两个命令生成和显示公钥的示例:

$ bitcoind getnewaddress
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
$ bitcoind dumpprivkey 1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

dumpprivkey 命令只是读取钱包中getnewaddress命令生成的公钥,然后显示出来。 bitcoind 无法从私钥中学习公钥。除非密钥对存储在钱包中,否则dumpprivkey命令只在钱包中有效。

dumpprivkey 命令无法从私钥中获取对应的公钥,因为不可能。该命令只提取钱包中已经存在的公钥,该公钥是由 ge 提取的 tnewaddress 命令生成的公钥。

您还可以使用命令行 sx 工具(参见“3.3.1Libbitcoin 和 sxTools”)通过 newkey 命令生成和显示公钥:

$ sx newkey
5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn

4.1.4 个私钥

私钥可以通过椭圆曲线除法从公钥估计出来,不可逆过程:K=k*G。其中 k 是公钥,G 是称为生成点的常数点,K 是生成的私钥。反向操作,被称为“寻找离散对数”——知道私钥K来找到公钥k——是非常困难的,就像尝试k的所有可能值一样,即蛮力搜索。在演示如何从公钥生成私钥之前,让我们稍微详细研究一下椭圆曲线密码学。

4.1.5 椭圆曲线密码学解释

椭圆曲线密码学是一种基于离散对数问题的非对称(或私钥)加密方法,可以通过椭圆曲线上的点进行分割或分割来表示。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

上图是椭圆曲线的示例,类似于比特币使用的曲线。

比特币使用特殊的椭圆曲线和一系列由 secp256256kk1 标准定义的物理常数。该标准由英国国家标准与技术研究院 (NIST) 制定。 secp256256kk1曲线由以下函数定义,形成椭圆曲线:

y2=(x3+7)}over(Fp)

y2modp=(x3+7)modp

上面的modp(素数p的模数)表示曲线在素数阶p的有限域中,也写为Fp,其中p=2256-232-29-28-27-26-24-1,这是一个非常大的合数。

比特币国际钱包网站_比特币硬件钱包怎么弄_比特币钱包 ios

因为这条曲线是在素数阶的有限域中定义的,而不是实数,它的函数图看起来像一个散布在二维上的散点图,因此很难用图形表示。然而,它背后的物理原理类似于真实范围内的椭圆曲线。作为一个反例,右图显示了一个小图。在一个 17 次素数的有限域中,有许多椭圆曲线以网格上一系列散点的形式出现。 secp256256kk1 的比特币椭圆曲线可以想象成一个非常大的网格上一系列更复杂的散点。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

图为:椭圆曲线密码学上的椭圆曲线F(p),其中p=17

下面作为反例,这是secp256256kk1曲线上的点P,其坐标为(x, y)。你可以使用 Python 来检查它:

P =(55066263022277343669578718895168534326250603453777594175500187360389116729240,32670510020758816978083085130507043184471273380659243275938904335757337482424)
Python 3.4.0 (default, Mar 30 2014, 19:23:13)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
>>> x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
>>> y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
>>> (x ** 3 + 7 - y**2) % p
0

椭圆曲线上 在 的物理学中,有一个点叫做“无穷远点”,大致相当于0在乘法中的作用。在计算机中,有时表示为 X=Y=0(虽然这不满足椭圆曲线多项式,但可以作为特例进行测试)。还有一个+运算符,叫“加法”,就像中学物理里的实数相乘。给定一条椭圆曲线上的两个点P1和P2,椭圆曲线一定有第三个点P3=P1+P2。

在几何图形中,第三点P3可以通过在P1和P2之间画一条线来确定。这条线正好与椭圆曲线上的一个点相交。该点记录为 P3'=(x, y)。之后,在 x 轴上做一个映射得到 P3=(x, -y)。

以下是一些可以解释“无穷大点”的点,有特殊情况需要。如果 P1 和 P2 是同一点,则连接 P1 和 P2 的线是点 P1 的切线。曲线上只有一个与切线相交的新点。切线的斜率可以通过微分得到。虽然将曲线点限制在两个整数坐标也可以求出斜率!

在个别情况下(即,如果 P1 和 P2 具有相同的 x 值,但不同的 y 值),切线将完全垂直。在这些情况下,P3 =“指向无穷远”。

如果 P1 是“无限远点”,那么它的和是 P1+P2=P2。类似地,当 P2 在无穷大点时,则 P1+P2=P1。这是为了让无穷大点类似于0的效果。

原来这里的+操作符是关联的,意思是(A+B)C=A(B+C)。这意味着我们可以写出不带括号的 A+B+C 而不会混淆。

此时,我们已经定义了椭圆乘法。为了扩展乘法,我们有一个标准的加法定义。给定椭圆曲线上的点 P,如果 k 是整数,则 kP=P+P+P+…+P(k 次)。请注意,k 有时会被混淆并称为“指数”。

4.1.6 生成私钥

从一个随机生成的公钥k开始,我们将其与曲线上定义的生成点除以G得到曲线上的另一个点,即对应的私钥K。生成点是secp256256kk1标准的一部分,并且比特币密钥的生成点是一样的:

K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G

其中k是公钥,G是生成点,这条曲线上的结果点K就是私钥。由于所有比特币用户的生成点都是相同的,所以一个公钥 k 除以 G 会得到相同的私钥 K。 k 和 K 的关系是固定的,但只能双向操作,即K 是从 k 中获得的。这是能够在不泄露公钥 (k) 的情况下与任何人共享比特币地址(K 的派生)的动机。

由于物理操作是双向的,所以公钥可以转为私钥,但私钥不能转回公钥。

为了实现椭圆曲线加法,我们将之前形成的公钥k和生成点G相加得到私钥K:

K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G

私钥K定义为点K=(x,y):

K = (x, y)
其中,
x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

为了演示整数点的相加,我们将在实数范围内使用更简单的椭圆曲线。请记住,物理学是相同的。我们的目标是找到生成点 G 的倍数 kG。即 G 乘以 k 次。在椭圆曲线中,乘以一个点相当于从该点画一条切线,找到另一个与曲线相交的点,然后映射到x轴。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

上图是曲线上得到G、2G、4G的几何运算。

大多数比特币程序使用 OpenSSL 密码库进行椭圆曲线估计。例如,可以通过调用 EC_POINT_mul() 函数来估计私钥。

4.2比特币地址

比特币地址是一串数字和字母,可以与任何想给你比特币的人共享。从私钥(也由数字和字母组成的字符串)生成的比特币地址以数字“1”开头。下面是一个比特币地址的例子:

1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

在一笔交易中,比特币地址通常作为收款人出现。如果把比特币交易称为收据,那么比特币地址就是收款人,也就是我们要在收款人栏中写的。收款人可能是建行账户、公司、机构,甚至是现金收据。汇票不指定特定帐户,而是使用通用名称作为收款人,这使其成为一种相当灵活的支付工具。同样,比特币地址的使用使比特币交易看起来很灵活。一个比特币地址可以代表一对私钥和公钥的拥有者,或者其他东西,比如第 132 页“P2SH(Pay-to-Script-Hash)”部分中提到的支付脚本。现在,让我们看一下从私钥生成比特币地址的简单示例。

比特币地址可以通过双向加密哈希算法得到私钥。哈希算法是一种双向函数,它接受任意宽度的输入以形成指纹摘要。加密哈希函数在比特币中被广泛使用:比特币地址、脚本地址和挖矿中的工作量证明算法。用于从私钥生成比特币地址的算法有 SecureHashAlgorithm(SHA) 和 RACEIntegrityPrimitivesEvaluationMessageDigest(RIPEMD),尤其是 SHA256 和 RIPEMD160。

以私钥K为输入,估计其SHA256哈希值,并用结果估计RIPEMD160哈希值,得到一个宽度为160位(20字节)的数:

A = RIPEMD160(SHA256(K))

公式中,K为私钥,A为生成的比特币地址。

比特币地址与私钥不同。比特币地址是通过双向哈希函数从私钥生成的。

普通用户看到的比特币地址是“Base58Check”编码的(参见第 72 页的“Base58 和 Base58Check 编码”部分),它使用 58 个字符(Base58 编号系统)和校准代码来增强可读性、避免歧义和有效避免地址转写和输入错误。 Base58Check 编码也用于比特币的其他地方,例如比特币地址、私钥、加密密钥和脚本哈希,以增强可读性和正确输入。在下一节中,我们将详细解释 Base58Check 的编码机制及其产生的结果。右图描述了如何从私钥生成比特币地址。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

4.2.1Base58 和 Base58Check 编码

为了更简洁方便地表示一长串数字,许多计算机系统使用小于十的补码表示数字和字母。例如,传统的十进制补码计数系统使用十位数字 0-9,而十六进制补码系统使用额外的六个字母 A-F。相同数字的 16 的补码表示比 10 的补码表示短。此外,Base64 使用 26 个大写字母、26 个小写字母、10 个数字和两个符号(例如“+”和“/”)在电子邮件数据等基于文本的媒体中传输二进制补码。 Base64 通常用于对 SMS 消息中的附件进行编码。 Base58 是一种基于文本的二进制补码编码格式,用于比特币和其他加密货币。这些编码格式除了实现数据压缩外,还保持了易读性,还具有错误诊断的功能。 Base58 是 Base64 编码格式的子集,同样使用大小写字母和 10 位数字,但丢弃了一些在特定字体中容易误读和混淆的字符。具体来说,Base58中不包含0(数字0)、O(小写字母o)、l(大写字母L)、I(小写字母i)以及Base64中的“+”和“/”两个字符。简而言之,Base58 由大小写字母和数字组成,不包括 (0, O, l, I)。

示例 4-1 比特币的 Base58 字母表

123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

Base58Check 是比特币中常用的 Base58 编码格式,它减少了错误校准代码以检测数据转录中的错误。校准码长 4 个字节,添加到要编码的数据中。校准码是从要编码的数据的哈希中获得的,因此可以用来衡量和防止转录和输入中的错误。使用Base58check编码格式时,编码软件会计算出原始数据的校准码与结果数据自带的校准码进行比较。如果两者不匹配,则说明有错误,因此Base58Check格式的数据无效。例如,不正确的比特币地址不会被黑客入侵。该文件夹被视为有效地址,否则这些错误将导致资金损失。

为了使用 Base58Check 编码格式对数据(数字)进行编码比特币硬件钱包怎么弄,首先我们需要在数据中添加一个“版本字节”。 Prefix,这个前缀用来指定要编码的数据的类型。例如,比特币地址的前缀是 0(16 的补码是 0x00),而公钥的前缀是 128(16 的补码)。它是 0x80)。表 4-1 列出了一些常见的版本前缀。

比特币钱包 ios_比特币硬件钱包怎么弄_比特币国际钱包网站

连接起来,我们估计“双哈希”校验码,即前面的结果(前缀)和数据)运行两次SHA256哈希算法:

checksum = SHA256(SHA256(prefix+data))

在生成的 32 字节长散列(两个散列)中,我们只取前 4 个字节。这 4 个字节用作校准代码。然后将校准代码添加到数据中。

结果由三部分组成:前缀、数据和校准代码。此结果使用前面描述的 Base58 字母表进行编码。右图描述了Base58Check编码的过程。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

Base58Check encoding:Base58 formatted, versioned, 校准后的格式,能清晰编码比特币数据的编码格式

在比特币中,大部分需要展示给用户的数据都是经过Base58Check编码的,可以实现数据压缩,易读且有错误校验。 Base58Check编码中的版本前缀是数据的格式容易区分,编码后的数据头包含明确的属性。此属性使用户可以轻松了解编码数据的类型以及如何使用它们。例如,我们可以看出它们的区别,Base58Check编码的比特币地址以1开头,而Base58Check编码的公钥WIF以5开头。表4-1显示了一些版本前缀及其对应的Base58格式。

表4-1Base58Check版本前缀及编码结果

类型版本前缀(十六进制)Base58格式回顾比特币地址形成的完整过程,从公钥,到私钥(椭圆曲线上的一个点),到两个哈希的地址,最后到Base58Check 格式的比特币地址。示例 4-2 中的 C++ 代码详细显示了从公钥到 Base58Check 编码的比特币地址的步骤。该代码使用“3.3 其他客户端、库、工具包”部分中描述的 libbitcoin 库来实现各个辅助功能。

示例 4-2 从公钥形成一个 Base58Check 编码的比特币地址

#include 
int main() {
    // Private secret key.
    bc::ec_secret secret = bc::decode_hash(
        "038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776");
    // Get public key.
    bc::ec_point public_key = bc::secret_to_public_key(secret);
    std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;
    // Create Bitcoin address.
    // Normally you can use:
    //   bc::payment_address payaddr;
    //   bc::set_public_key(payaddr, public_key);
    //   const std::string address = payaddr.encoded();
    // Compute hash of public key for P2PKH address.
    const bc::short_hash hash = bc::bitcoin_short_hash(public_key);
    bc::data_chunk unencoded_address; // Reserve 25 bytes
    // [ version:1 ]
    // [ hash:20 ]
    //   [ checksum:4 ]
    unencoded_address.reserve(25);
    // Version byte, 0 is normal BTC address (P2PKH).     unencoded_address.push_back(0);
    // Hash data
    bc::extend_data(unencoded_address, hash);
    // Checksum is computed by hashing data, and adding 4 bytes from hash. bc::append_checksum(unencoded_address);
    // Finally we must encode the result in Bitcoin's base58 encoding assert(unencoded_address.size() == 25);
    const std::string address = bc::encode_base58(unencoded_address);
    std::cout << "Address: " << address << std::endl;
    return 0; 
}

如编译运行addr代码所示是的,因为代码使用了预定义的公钥,所以每次运行都会形成相同的比特币地址。如例4-3所示。

示例4-3 编译运行addr代码

# Compile the addr.cpp code
$ g++ -o addr addr.cpp $(pkg-config --cflags --libs libbitcoin)
# Run the addr executable
$ ./addr
Public key: 0202a406624211f2abbdc68da3df929f938c3399dd79fac1b51b0e4ad1d26a47aa Address: 1PRTTaJesdNovgne6Ehcdu1fpEdX7913CK

4.2.2键格式

私钥和公钥都可以以多种格式编码。以不同格式对密钥进行编码后,虽然结果可能看起来不同,但密钥中编码的数字不会改变。这种不同的编码格式主要是为了方便人们正确使用和识别密钥。

公钥格式

公钥可以用多种不同的格式表示,所有这些格式都对应同一个 256 位数字。表 4-2 显示了三种常见的公钥格式。

表 4-2 公钥表示(编码格式)

类型版本说明HexNone64hexadecimaldigitsWIFdigitsWIF55BaseBase58Checkencoding:Base58withversionprefixof128and32-bitchecksumWIF-compressedKorLA以上,with addedsuffix0x01beforeencoding

表 4-3 显示了以这三种格式生成的公钥。

示例:同样的表格,不同的格式

格式公钥Hex1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDDWIF5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1JcnWIF-compressedKxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

这种表示法都是拿来表示同一个号码,同一个公钥的不同方式。事实上,编码后的字符串看起来不同,但不同的格式可以很容易地相互转换。

将 Base58Check 编码解码为 16 的补码

sx 工具包(参见“3.3.1Libbitcoin 和 sxTools”)可用于对比特币密钥、地址和交易的一些操作 Shell 脚本和命令行“管道”进行编程。您还可以使用 sx 工具从命令行解码 Base58Check 格式。

我们使用的命令是base58check-decode:

$ sx base58check-decode 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn
1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd 128

结果是16的补码,后跟皮肤文件夹导出格式(WalletImportFormat,WIF)的版本前缀是128。

将 16 的补码转换为 Base58Check 代码

要转换成Base58Check代码(与上一条命令正好相反),我们需要提供16的补码公钥和钱包导出格式(WalletImportFormat,WIF)的版本号前缀为128:

$sx base58check-encode 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd 128 
5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn

将十六进制(压缩格式密钥)转换为 Base58Check 编码

要将压缩格式的公钥编码为Base58Check(参见“压缩格式的公钥”部分),我们需要在16的补码中的公钥旁边添加后缀01,然后使用与之前相同的方法:

K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

生成的WIF压缩格式公钥以字母“K”开头,表示编码后的公钥有后缀“01”,公钥只能用于生成压缩格式的私钥(见章节"压缩格式的私钥")。

私钥格式

私钥也可以用许多不同的格式来表示。

从上面我们知道,私钥是椭圆曲线上的一个点,由一对坐标(x,y)组成。私钥通常由前缀 04 后跟两个 256 位数字表示。其中一个 256 位数字是私钥的 x 坐标,另一个 256 位数字是 y 坐标。前缀04用于区分未压缩格式的私钥,压缩格式的私钥以02或03开头。

底部是上一篇文章中公钥生成的私钥,其坐标x和y如下:

x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

底部是相同的私钥以 520 位数字(130 个十六进制数字)表示。这个 520 位的数字以前缀 04 开头,后跟 x 和 y 坐标,格式为 04xy:

比特币钱包 ios_比特币国际钱包网站_比特币硬件钱包怎么弄

K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

压缩格式的私钥

引入压缩格式的私钥的目的是为了减少比特币交易的字节数,从而节省这些运行区块链数据库的节点的c盘空间。大多数比特币交易都包含私钥,用于验证用户的凭据并以比特币支付。每个私钥有 520 位(包括前缀、x 坐标、y 坐标)。如果每个区块有数百笔交易,每晚发生数千笔交易,就会有大量数据写入区块链。

正如我们在“4.1.4 私钥”一节中看到的,私钥是椭圆曲线上的一个点 (x,y)。椭圆曲线实际上是一个物理多项式,曲线上的点实际上是多项式的解。因此,如果我们知道私钥的 x 坐标,我们可以通过求解多项式 y2modp=(x3+7)modp 得到 y 坐标。这些方案允许我们只存储私钥的 x 坐标key, 省略 y 因此,私钥的大小和存储空间减少了 256 位比特币硬件钱包怎么弄,每笔交易所需的字节数减少了近一半,随着时间的推移大大节省了大量的数据传输和存储。

未压缩格式的私钥以04为前缀,而压缩格式的私钥以02或03为前缀。之所以需要这两个不同的前缀,是因为公式右边为椭圆曲线加密是 y2,也就是说 y 的解来自一个平方根,它可能是正的,也可能是负的。更形象地说,y坐标可能在x坐标轴的前面或下面。从图 4-2 中的椭圆曲线图可以看出,该曲线是对称的,从 x 轴上看,就像一个对称的全身镜的两侧。因此,如果我们省略 y 坐标,我们必须存储 y 的符号(正或负)。也就是说,对于给定的x值,我们需要知道y值是在x轴的前面还是下面,因为它们代表椭圆曲线上的不同点,也就是不同的私钥。当我们用二进制补码算法估计素数p阶的有限域时,用椭圆曲线时,y坐标可能是素数也可能是素数,对应于上面提到的y值的正负号。为此,为了区分y坐标的两个可能值,当我们生成压缩格式的私钥时,如果y是质数,则使用02作为前缀;如果 y 是素数,则使用 03 作为前缀。这样就可以根据私钥中给出的x值正确推导出对应的y坐标,从而可以将私钥解码压缩为一条椭圆曲线上的完整点坐标。右图说明了私钥压缩:

区块链的第一应用---比特币,之 (密钥、地址、钱包)

下面是上一节生成的私钥,使用264位(66个十六进制数字)的压缩私钥格式,其中前缀03表示y坐标是质数:

K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

This compressed format private key corresponds to the same public key, which means that it is generated by the same public key. And the compressed format private key and the non-compressed format private key are very different. More importantly, if we use double hash The hash function (RIPEMD160(SHA256(K))) converts the compressed private key into a bitcoin address, and the resulting address will be different from the address formed by the uncompressed private key. These results can be confusing, because a public key Two different formats of private keys can be generated—compressed and uncompressed, and the private keys in these two formats can generate two different bitcoin addresses. And the public keys of these two different bitcoin addresses are The same.

The compressed private key format has gradually become the default format for various Bitcoin clients, which can greatly reduce the number of bytes required for transactions, while also allowing the storage of the blockchain. C drive space becomes smaller. However, not all clients support private keys in compressed format, so these newer Clients that support private keys in compressed format have to consider how to handle transactions from older clients that do not support private keys in compressed format. This is especially important when the wallet application is exporting the public key of another wallet application, since the new wallet needs to scan the blockchain and find all transactions related to those exported public keys.比特币钱包应该扫描哪个比特币地址? The new client does not know which private key to use: since both the Bitcoin address formed by the compressed private key or the address formed by the uncompressed private key are both legitimate Bitcoin addresses, both can be published. The keys are signed correctly, and they are completely different bitcoin addresses.

To address this issue, newer bitcoin clients will use a different wallet export format (WalletImportFormat) when public keys are imported from wallet. These new wallet export formats can be used to indicate that the public key has already been used to generate a compressed private key, and the generated bitcoin address is also based on the compressed private key. This solution can solve the problem of whether the exported public key comes from the old wallet or the new wallet, and also solves the problem of whether the Bitcoin address generated by the private key comes from the compressed private key or the uncompressed private key. Finally, when the new wallet scans the blockchain, it can use the corresponding bitcoin address to find out the transactions that occurred in the blockchain by the bitcoin address. We will explain in detail how these mechanisms work in the next section.

Compressed public key

Actually "compressed public key" is a deception in name, because when a public key is imported using WIF compressed format, not only is there no compression , and is one byte longer than the "uncompressed" private key.这个额外的字节是公钥后缀为01,表示公钥来自较新的钱包,只能用于生成压缩私钥。 Public keys are uncompressed and cannot be compressed. "Compressed public key" actually just means "public key used to generate the private key in compressed format", while "uncompressed public key" is used to mean "public key used to generate the private key in uncompressed format". In order to prevent more misunderstandings, it should only be said that the import format is "WIF compressed format" or "WIF", but not that the public key is "compressed".

It is important to note that this format is not used interchangeably. In newer wallets that implement private keys in compressed format, public keys can only and always be imported as WIF compressed format (prefixed with K or L). For older wallets that do not implement the private key in compressed format, the public key will only be imported in WIF format (prefixed with 5). The purpose of this is to give a signal to the wallet that derives those public keys: whether to scan the blockchain with compressed private keys and bitcoin addresses, or uncompressed private keys and bitcoin addresses.

If a bitcoin wallet implements a compressed private key, then it will use that compressed private key in all transactions. The public key in the wallet will be used to generate the compressed private key, and the compressed private key will be used to generate the bitcoin address in the transaction. When importing a public key from a Bitcoin wallet that implements a compressed private key, the wallet export format (WIF) will be changed to the WIF compressed format, which will append a byte-sized Suffix 01. The resulting public key in Base58Check encoded format is called a WIF ("compressed") public key and begins with the letters "K" or "L". Whereas the ones starting with "5" are public keys imported in WIF (uncompressed) format from older wallets.

表4-4展示了同样的公钥使用不同的WIF和WIF压缩格式编码。

表4-4示例:同样的公钥,不同的格式

格式公钥Hex1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDDWIF5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1JcnHex-compressed1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD01WIF-compressedKxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

“压缩格式公钥”是一个不当用词!公钥不是压缩的。 WIF压缩格式的公钥只是拿来表明她们只能被生成压缩的私钥和对应的比特币地址。相反地,“WIF压缩”编码的公钥还多出一个字节,由于这些公钥多了后缀“01”。该后缀是拿来分辨“非压缩格式”私钥和“压缩格式”私钥。

4.3用Python实现秘钥和比特币地址

最全面的比特币Python库是VitalikButerin写的pybitcointools。在例4-4中,我们使用pybitcointools库(导出为“bitcoin”)来世成和显示不同格式的秘钥和比特币地址。

例4-4使用pybitcointools库的秘钥和比特币地址的生成和低格过

import bitcoin
# Generate a random private key
valid_private_key = False while not valid_private_key:
    private_key = bitcoin.random_key()
    decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
    valid_private_key =  0 < decoded_private_key < bitcoin.N
print "Private Key (hex) is: ", private_key
print "Private Key (decimal) is: ", decoded_private_key
# Convert private key to WIF format
wif_encoded_private_key = bitcoin.encode_privkey(decoded_private_key, 'wif')
print "Private Key (WIF) is: ", wif_encoded_private_key
# Add suffix "01" to indicate a compressed private key
compressed_private_key = private_key + '01'
print "Private Key Compressed (hex) is: ", compressed_private_key
# Generate a WIF format from the compressed private key (WIF-compressed)
wif_compressed_private_key = bitcoin.encode_privkey(
    bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif')
print "Private Key (WIF-Compressed) is: ", wif_compressed_private_key
# Multiply the EC generator point G with the private key to get a public key point
public_key = bitcoin.base10_multiply(bitcoin.G, decoded_private_key) print "Public Key (x,y) coordinates is:", public_key
# Encode as hex, prefix 04
hex_encoded_public_key = bitcoin.encode_pubkey(public_key,'hex') print "Public Key (hex) is:", hex_encoded_public_key
# Compress public key, adjust prefix depending on whether y is even or odd
(public_key_x, public_key_y) = public_key if (public_key_y % 2) == 0:
    compressed_prefix = '02' 
else:
    compressed_prefix = '03'
hex_compressed_public_key = compressed_prefix + bitcoin.encode(public_key_x, 16) print "Compressed Public Key (hex) is:", hex_compressed_public_key
# Generate bitcoin address from public key
print "Bitcoin Address (b58check) is:", bitcoin.pubkey_to_address(public_key)
# Generate compressed bitcoin address from compressed public key
print "Compressed Bitcoin Address (b58check) is:", \             bitcoin.pubkey_to_address(hex_compressed_public_key)

例4-5显示了上段代码运行结果。

例4-5运行key-to-address-ecc-example.py

$ python key-to-address-ecc-example.py
Private Key (hex) is:
 3aba4162c7251c891207b747840551a71939b0de081f85c4e44cf7c13e41daa6
Private Key (decimal) is:
 26563230048437957592232553826663696440606756685920117476832299673293013768870
Private Key (WIF) is:
 5JG9hT3beGTJuUAmCQEmNaxAuMacCTfXuw1R3FCXig23RQHMr4K
Private Key Compressed (hex) is:
 3aba4162c7251c891207b747840551a71939b0de081f85c4e44cf7c13e41daa601
Private Key (WIF-Compressed) is:
 KyBsPXxTuVD82av65KZkrGrWi5qLMah5SdNq6uftawDbgKa2wv6S
Public Key (x,y) coordinates is:
 (41637322786646325214887832269588396900663353932545912953362782457239403430124L,
 16388935128781238405526710466724741593761085120864331449066658622400339362166L)
Public Key (hex) is:
 045c0de3b9c8ab18dd04e3511243ec2952002dbfadc864b9628910169d9b9b00ec↵
243bcefdd4347074d44bd7356d6a53c495737dd96295e2a9374bf5f02ebfc176
Compressed Public Key (hex) is:
 025c0de3b9c8ab18dd04e3511243ec2952002dbfadc864b9628910169d9b9b00ec
Bitcoin Address (b58check) is:
 1thMirt546nngXqyPEz532S8fLwbozud8
Compressed Bitcoin Address (b58check) is:
 14cxpo3MBCYYWCgF74SWTdcmxipnGUsPw3

例4-6是另外一个示例,使用的是PythonECDSA库来做椭圆曲线估算而非使用bitcoin的库。

例4-6使用在比特币秘钥中的椭圆曲线算法的脚本

import ecdsa
import random
from ecdsa.util import string_to_number, number_to_string
# secp256k1, http://www.oid-info.com/get/1.3.132.0.10
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
oid_secp256k1 = (1, 3, 132, 0, 10)
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1,
oid_secp256k1)
ec_order = _r
curve = curve_secp256k1
generator = generator_secp256k1
def random_secret():
    random_char = lambda: chr(random.randint(0, 255))
    convert_to_int = lambda array:     int("".join(array).encode("hex"), 16) 
    byte_array = [random_char() for i in range(32)]
    return convert_to_int(byte_array)
def get_point_pubkey(point): 
    if point.y() & 1:
        key = '03' + '4x' % point.x() 
    else:
        key = '02' + '4x' % point.x() 
    return key.decode('hex')
def get_point_pubkey_uncompressed(point): 
    key='04'+\
        '4x' % point.x() + \
        '4x' % point.y() 
    return key.decode('hex')
# Generate a new private key.
secret = random_secret() 
print "Secret: ", secret
# Get the public key point.
point = secret * generator 
print "EC point:", point
print "BTC public key:", get_point_pubkey(point).encode("hex")
# Given the point (x, y) we can create the object using:
point1 = ecdsa.ellipticcurve.Point(curve, point.x(), point.y(), ec_order) 
assert point1 == point

例4-7显示了运行脚本的结果。

例4-7安装PythonECDSA库,运行ec_math.py脚本

running the ec_math.py script
$ # Install Python PIP package manager
$ sudo apt-get install python-pip
$ # Install the Python ECDSA library
$ sudo pip install ecdsa
$ # Run the script
$ python ec-math.py
Secret:
38090835015954358862481132628887443905906204995912378278060168703580660294000
EC point:
(70048853531867179489857750497606966272382583471322935454624595540007269312627,
105262206478686743191060800263479589329920209527285803935736021686045542353380)
BTC public key: 029ade3effb0a67d5c8609850d797366af428f4a0d5194cb221d807770a1522873

4.4比特币皮夹

皮夹是公钥的容器,一般通过有序文件或则简单的数据库实现。另外一种制做公钥的途径是确定性秘钥生成。在这儿你可以用原来的公钥,通过双向哈希函数来世成每一个新的公钥,并将新生成的秘钥按次序联接。只要你可以重新创建这个序列,你只须要第一个公钥(也称种子、主公钥)来世成它们。在本节中,我们将会检测不同的公钥生成方式及其皮夹结构。

比特币皮夹只包含公钥而不是比特币。每一个用户有一个包含多个公钥的皮夹。皮夹中包含成对的公钥和私钥。用户用这种公钥来签名交易,因而证明它们拥有交易的输出(也就是其中的比特币)。比特币是以交易输出的方式来储存在区块链中(一般记为vout或txout)。

4.4.1非确定性(随机)皮夹

在最早的一批比特币顾客端中,皮夹只是随机生成的公钥集合。这种类型的皮夹被叫做零型非确定皮夹。举个事例,比特币核心顾客端预先生成100个随机公钥,从最开始就生成足够多的公钥而且每把锁匙只使用一次。这种类型的皮夹有一个爱称“JustaBunchOfKeys(一堆公钥)”简称JBOK。这些皮夹如今正在被确定性皮夹替换,由于它们无法管理、备份以及导出。随机锁匙的缺点就是假如你生成好多,你必须保存它们所有的副本。这就意味着这个皮夹必须被常常性地备份。每一把锁匙都必须备份,否则一旦皮夹不可访问时,皮夹所控制的资金就付之东流。此类情况直接与防止地址重复使用的原则相冲突——每个比特币地址只能用一次交易。地址通过关联多重交易和对方的地址重复使用会降低隐私。 0型非确定性皮夹并不是皮夹的好选择,尤其是当你不想重复使用地址而创造过多的公钥而且要保存它们。其实比特币核心顾客包含0型皮夹,但比特币的核心开发者并不想鼓励你们使用。右图表示包含有松散结构的随机锁匙的集合的非确定性皮夹。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

4.4.2确定性(种子)皮夹

确定性,或则“种子”钱包包含通过使用单项离散多项式而可从公共的种子生成的公钥。种子是随机生成的数字。这个数字也富含例如索引号码或则可生成公钥的“链码”(参见“4.4.4分层确定性皮夹(BIP0032/BIP0044)”一节)。在确定性皮夹中,种子足够收回所有的早已形成的公钥,所以只用在初始创建时的一个简单备份就足以搞定。而且种子也足够让皮夹输入或则输出。这就很容易容许使用者的公钥在皮夹之间轻松转移输入。

4.4.3助记码词汇

助记码词汇是英语词组序列代表(编码)用作种子对应所确定性皮夹的随机数。词组的序列足以重新创建种子,但是从种子哪里重新创造皮夹以及所有公钥。在首次创建皮夹时,带有助记码的,运行确定性皮夹的皮夹的应用程序将会向使用者展示一个12至24个词的次序。词组的次序就是钱包的备份。它也可以被拿来恢复以及重新创造应用程序相同或则兼容的皮夹的锁匙。助记码代码可以让使用者复制皮夹更容易一些,由于它们相比较随机数字次序来说,可以很容易地被读下来而且正确抄录。

比特币硬件钱包怎么弄_比特币国际钱包网站_比特币钱包 ios

助记码被定义在比特币的改进建议39中(参见"附表2比特币改进合同[bip0039]”),目前还处于草案状态。需注意的是,BIP0039是一个建议草案而不是标准方案。具体地来说,电子皮夹和BIP0039使用不同的标准且对应不同组的词汇。Trezor皮夹以及一些其他皮夹使用BIP0039,然而BIP0039和电子皮夹的运行不兼容。

BIP0039定义助记码和种子的创建过程如下:

1.创造一个128到256位的随机次序(熵)。2.提出SHA256哈希前几位,就可以创造一个随机序列的校准和。3.把校准和加在随机次序的旁边。4.把次序分解成11位的不同集合,并用这种集合去和一个预先早已定义的2048个词组字典做对应。5.生成一个12至24个词的助记码。

表4-5表示了熵数据的大小和助记码词组的宽度之间的关系。

表4-5助记码:熵及数组宽度

熵(bits)校准符(bits)熵+校准符数组长128413212160516515192619818224723121256826424

助记码表示128至256位数。这可以通过使用公钥抻拉函数PBKDF2来导入更长的(512位)的种子。所得的种子可以拿来创造一个确定性皮夹以及其所派生的所有锁匙。

表4-6和表4-7展示了一些助记码的事例和它所生成的种子。

表4-6128位熵的助记码以及所形成的种子

负熵输入(128bits)0c1e24e5917779d297e14d45f14e1a1a助记码(12个词组)armyvandefensecarryjealoustruegarbageclaimechomediamakecrunch种子(512bits)3338a6d2ee71c7f28eb5b882159634cd46a898463e9d2d0980f8e80dfbba5b0fa0291e5fb888a599b44b93187be6ee3ab5fd3ead7dd646341b2cdb8d08d13bf

表4-7256位熵的助记码以及所形成的种子

负熵输入(256bits)2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c助记码(24个词组)cakeappleborrowsilkendorsefitnesstopdenialcoilriot

staywolfluggageoxygenfaintmajoreditmeasureinvitelovetrapfield

dilemmaoblige种子(512bits)3972e432e99040f75ebe13a660110c3e29d131a2c808c7ee5f1631d0a977fcf473bee22

fce540af281bf7cdeade0dd2c1c795bd02f1e4049e205a0158906c343

4.4.4分层确定性皮夹(BIP0032/BIP0044)

确定性皮夹被开发成更容易从单个“种子”中生成许多关键的锁匙。最中级的来自确定性皮夹的形是通过BIP0032标准生成的thehierarchicaldeterministicwalletorHDwalletdefined。分层确定性皮夹包含从数结构所生成的锁匙。这些母锁匙可以生成子锁匙的序列。这种子锁匙又可以衍生出孙锁匙,借以无穷类推。这个树结构表如右图所示。

区块链的第一应用---比特币,之 (密钥、地址、钱包)

假如你想安装运行一个比特币皮夹,你须要建造一个符合BIP0032和BIP0044标准的HD皮夹。

HD皮夹提供了随机(不确定性)锁匙有两个主要的优势。第一,树形结构可以被拿来抒发额外的组织含意。例如当一个特定分支的子秘钥被拿来接收交易收入而且有另一个分支的子秘钥拿来负责支付耗费。不同分支的秘钥都可以被用在企业环境中,这就可以支配不同的分支部门,子公司,具体功能以及会计类别。

HD皮夹的第二个益处就是它可以容许让使用者去构建一个公共秘钥的序列而不须要访问相对应的公钥。这可容许HD皮夹在不安全的服务器中使用或则在单笔交易中发行不同的公共锁匙。公共锁匙不须要被预先加载或则提早衍生,而且在服务器中不具有可拿来支付的公钥。

从种子中创造HD皮夹

HD皮夹从单个rootseed中创建,为128到256位的随机数。 HD皮夹的所有的确定性都衍生自这个根种子。任何兼容HD皮夹的根种子也可重新创造整个HD皮夹。所以简单的转移HD皮夹的根中斯就让HD皮夹中所包含的成千上百万的秘钥被复制,存储导入以及导出。根种子通常总是被表示为amnemonicwordsequence,正如"4.4.3助记码词汇"一节所叙述的,助记码词汇可以让人们更容易地抄录和存储。

创建主秘钥以及HD皮夹地主链代码的过程如右图所示。

根种子输入到HMAC-SHA512算法中就可以得到一个可拿来创造masterprivatekey(m)和amasterchaincode的哈希。主公钥(m)以后可以通过使用我们在本章以前见到的那种普通椭圆曲线m*G过程生来成相对应的主私钥(M)。链代码可以给从母秘钥中创造子秘钥的那种多项式中引入的熵。

私有子秘钥的衍生

分层确定性皮夹使用CKD(childkeyderivation)等式去从母秘钥衍生出子秘钥。

子秘钥衍生多项式是基于单项哈希多项式。这个等式结合了:

•一个母公钥或则公共锁匙(ECDSA未压缩键)•一个称作链码(256bits)的种子•一个索冒号(32bits)

链码是拿来给这个过程引入看似的随机数据的,致使索引不能充分衍生其他的子秘钥。因而,有了子秘钥并不能让它发觉自己的相像子秘钥,除非你已然有了链码。最初的链码种子(在密码树的内侧)是用随机数据构成的,此后链码从各自的母链码中衍生下来。

这三个项目相结合并散列可以生成子秘钥,如下。

母公共锁匙——链码——以及索冒号合并在一起而且用HMAC-SHA512多项式散列以后可以形成512位的散列。所得的散列可被分拆为两部份。散列右半部份的256位产出可以给子链当链码。左半部份256位散列以及索引码被加载在母公钥上来衍生子公钥。在图4-11中,我们看见这些这个说明——索引集被设为0去生产母秘钥的第0个子秘钥(第一个通过索引)。

图4-11延长母公钥去创造子公钥

改变索引可以让我们延长母秘钥以及创造序列中的其他子秘钥。例如子0,子1,子2等等。每一个母秘钥可以右20亿个子秘钥。

向密码树下一层重复这个过程,每位子秘钥可以依次成为母秘钥继续创造它自己的子秘钥,直至无限代。

使用衍生的子秘钥

子公钥不能从非确定性(随机)秘钥中被分辨下来。由于衍生多项式是双向多项式,所以子秘钥不能被拿来发觉她们的母秘钥。子秘钥也不能拿来发觉她们的相同层级的姐妹秘钥。假如你有第n个子秘钥,你不能发觉它上面的(第n-1)或则前面的子秘钥(n+1)或则在同一次序中的其他子秘钥。只有母秘钥以及链码能够得到所有的子秘钥。没有子链码的话,子秘钥也不能拿来衍生出任何孙秘钥。你须要同时有子秘钥以及对应的链码能够创建一个新的分支来衍生出孙秘钥。

那子公钥自己可被用做哪些呢?它可以拿来做公共锁匙和比特币地址。以后它就可以被用那种地址来订立交易和支付任何东西。

子秘钥、对应的公共锁匙以及比特币地址都不能从随机创造的秘钥和地址中被分辨下来。事实是它们所在的序列,在创造她们的HD皮夹多项式之外是不可见的。一旦被创造下来,它们就和“正常”钥匙一样运行了。

扩充秘钥

正如我们之前听到的,秘钥衍生多项式可以被拿来创造锁匙树上任何层级的子秘钥。这只须要三个输入量:一个秘钥,一个链码以及想要的子秘钥的索引。秘钥以及链码这两个重要的部份被结合以后,就称作extendedkey。术语“extendedkey”也被觉得是“可扩充的秘钥”是由于这些秘钥可以拿来衍生子秘钥。

扩充秘钥可以简单地被存储而且表示为简单的将256位秘钥与256位链码所并联的512位序列。有两种扩充秘钥。扩充的公钥是公钥以及链码的结合。它可被拿来衍生子公钥(子公钥可以衍生子公共秘钥)公共锁匙以及链码组成扩充公共锁匙。这个锁匙可以拿来扩充子公共锁匙,见“4.1.6生成私钥”。

比特币国际钱包网站_比特币硬件钱包怎么弄_比特币钱包 ios

想像一个扩充秘钥作为HD皮夹中锁匙树结构的一个分支的根。你可以衍生出这个分支的剩下所有部份。扩充私人锁匙可以创建一个完整的分支而扩充公共锁匙只才能创造一个公共锁匙的分支。

一个扩充锁匙包括一个公钥(或则公共锁匙)以及一个链码。一个扩充秘钥可以创造出子秘钥而且能创造出在锁匙树结构中的整个分支。分享扩充锁匙就可以访问整个分支。

扩充秘钥通过Base58Check来编码,因而能轻易地在不同的BIP0032-兼容皮夹之间导出导入。扩充秘钥编码用的Base58Check使用特殊的版本号,这造成在Base58编码字符中,出现前缀“xprv”和“xpub”。这些前缀可以让编码更易被辨识。由于扩充秘钥是512或则513位,所以它比我们之前所见到的Base58Check-encoded串更长一些。

这是一个在Base58Check中编码的扩充公钥的反例:

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c

这是在Base58Check中编码的对应的扩充公共锁匙:

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

公共子锁匙推论

正如之前提到的,分层确定性皮夹的一个很有用的特性就是可以不通过公钥而直接从公共母锁匙派生出公共子锁匙的能力。这就给了我们两种去衍生子公共锁匙的方式:或则通过子公钥,再或则就是直接通过母公共锁匙。

因而,扩充的公共锁匙可以再HD皮夹结构的分支中,被拿来衍生所有的私钥(且只有公共锁匙)。

这些快捷方法可以拿来创造特别保密的public-key-only配置。在配置中,服务器或则应用程序不管有没有公钥,都可以有扩充公共锁匙的副本。这些配置可以创造出无限数目的公共锁匙以及比特币地址。并且不可以花送到这个地址里的任何比特币。与此同时,在另一种更保险的服务器上,扩充公钥可以衍生出所有的对应的可订立交易以及花钱的公钥。

这些方案的一个常见的方案是安装一个扩充的公共锁匙在服务电商公共程序的网路服务器上。网路服务器可以使用这个公共锁匙衍生多项式去给每一笔交易(例如顾客的购物车)创造一个新的比特币地址。但为了防止被盗,网路服务商不会有任何公钥。没有HD皮夹的话,惟一的方式就是在不同的安全服务器上创造成千上万个比特币地址,然后就提早上传到电商服务器上。这些技巧比较冗长并且要求持续的维护来确保电商服务器不“用光”公共锁匙。

这些解决方案的另一种常见的应用是冷冻或则硬件皮夹。在这些情况下,扩充的公钥可以被储存在纸质皮夹中或则硬件设备中(例如Trezor硬件皮夹)与此同时扩充公共锁匙可以在线保存。使用者可以依据意愿创造“接收”地址而公钥可以安全地在线下被保存。为了支付资金,使用者可以使用扩充的公钥离线签订比特币顾客或则通过硬件皮夹设备(例如Trezor)签订交易。图4-12论述了扩充母公共锁匙来衍生子公共锁匙的传递机制。

图4-12扩充母公共锁匙来创造一个子公共锁匙

硬化子秘钥的衍生

从扩充公共锁匙衍生一个分支公共锁匙的能力是很重要的,但牵涉一些风险。访问扩充公共锁匙并不能得到访问子私人秘钥的途径。并且,由于扩充公共锁匙包含有链码,如果子公钥被晓得或则被泄露的话,链码就可以被拿来衍生所有的其他子公钥。一个简单地泄漏的公钥以及一个母链码,可以曝露所有的子秘钥。更糟糕的是,子公钥与母链码可以拿来推测母公钥。

为了应对这些风险,HD皮夹使用一种称作hardenedderivation的取代衍生多项式。这就“打破”了母公共锁匙以及子链码之间的关系。这个硬化衍生多项式使用了母公钥去推到子链码,而不是母公共锁匙。这就在母/子次序中创造了一道“防火墙”——有链码但并不能否拿来估算子链码或则姐妹公钥。加强的衍生多项式看上去几乎与通常的衍生的子公钥相同,不同的是是母公钥被拿来输入散列多项式中而不是母公共锁匙,如图4-13所示。

图4-13子秘钥的加强衍生;忽视了母公共秘钥

当加强公钥衍生多项式被使用时,得到的子公钥以及链码与使用通常衍生多项式所得到的结果完全不同的。得到的秘钥“分支”可以被拿来生产不易被功击的扩充公共锁匙,由于它所含的链码不能被拿来开发或则曝露任何公钥。加强的衍生也因而被拿来在上一层级,使用扩充公共锁匙的的秘钥树中创造“间隙”。

简单地来说,假如你想要借助扩充公共锁匙的方便来衍生公共锁匙的分支而不将你自己曝露在窃取扩充链码的风险下,你应当从加强母公钥,而不是通常的母公钥,来衍生公共锁匙。最好的方法是,为了防止了推到出主锁匙,主锁匙所衍生的第一层级的子锁匙最好使用加强衍生。

正常衍生和加强衍生的索引号码

用在衍生多项式中的索引号码是32位的整数。为了分辨秘钥是从正常衍生多项式中衍生下来还是从加强衍生多项式中产出,这个索冒号被分为两个范围。索冒号在0和231–1(0x0to0x7FFFFFFF)之间的是只被用在常规衍生。索冒号在231和232–1(0x80000000to0xFFFFFFFF)之间的只被用在加强衍生多项式。因而,索冒号大于231就意味着子秘钥是常规的,而小于或则等于231的子秘钥就是加强型的。

为了让索引号码更容易被阅读和展示,加强子密码的索引号码是从0开始展示的,并且右上角有一个小撇号。第一个常规子秘钥因而被叙述为0,并且第一个加强子秘钥(索冒号为0x80000000)就被表示为0'。第二个加强秘钥依序有了索冒号0x80000001,且被显示为1',以这种推。当你听到HD皮夹索冒号i',这就意味着231+i。

HD皮夹秘钥辨识符(路径)

HD皮夹中的秘钥是用“路径”命名的,且每位级别之间用斜杠(/)字符来表示(见表4-8)。由主公钥衍生出的公钥起始以“m”打头。因而,第一个母秘钥生成的子公钥是m/0。第一个公共锁匙是M/0。第一个子秘钥的子秘钥就是m/0/1,以这种推。

秘钥的“祖先”是从右向左读,直至你达到了衍生出的它的主秘钥。举个反例,标示符m/x/y/z描述的是子秘钥m/x/y的第z个子秘钥。而子秘钥m/x/y又是m/x的第y个子秘钥。m/x又是m的第x个子秘钥。

表4-8HD皮夹路径的反例

HDpath秘钥描述m/0从主公钥(m)衍生出的第一个(0)子秘钥。m/0/0第一个私人子秘钥(m/0)的子秘钥。m/0'/0第一个子加强秘钥firsthardenedchild(m/0')的第一个常规子秘钥。m/1/0第2个子秘钥(m/1)的第一个常规子秘钥M/23/17/0/0主秘钥衍生出的第24个子秘钥所衍生出的第17个子秘钥的第一个子秘钥所衍生出的第一个子秘钥。

HD皮夹树形结构的导航

HD皮夹树形结构提供了极大的灵活性。每一个母扩充秘钥有40已个子秘钥:20亿个常规子秘钥和20亿个加强子秘钥。而每位子秘钥又会有40亿个子秘钥而且以这种推。只要你乐意,这个树结构可以无限类推到无穷代。并且,又因为有了这个灵活性,对无限的树形结构进行导航就显得异常困难。尤其是对于在不同的HD皮夹之间进行转移交易,由于内部组织到内部分支以及亚分支的可能性是无穷的。

两个比特币改进建议(BIPs)提供了这个复杂问的解决办法——通过创建几个HD皮夹树的提议标准。BIP0043提出使用第一个加强子索引作为特殊的标示符表示树形结构的“purpose”。基于BIP0043,HD皮夹应当使用且只用第一层级的树的分支,并且有索引号码去辨识结构而且有命名空间来定义剩余的树的目的地。举个反例,HD皮夹只使用分支m/i'/是为了表明哪个被索冒号“i”定义的特殊为目地。

在BIP0043标准下,为了延长的那种特殊规范,BIP0044提议了多帐户结构作为“purpose”。所有遵守BIP0044的HD皮夹根据只使用树的第一个分支的要求而被定义:m/44'/。

BIP0044指定了包含5个预定义树形层级的结构:

m / purpose' / coin_type' / account' / change / address_index

第一层的目的地总是被设定为44'。第二层的“coin_type”特指密码货币硬币的种类而且允许多元货币HD皮夹中的货币在第二个层级下有自己的亚树形结构。目前有三种货币被定义:Bitcoinism/44'/0'、BitcoinTestnetism/44'/1',以及Litecoinism/44'/2'。

树的第三层级是“account”,这可以容许使用者为了会计或则组织目的,而去再细分她们的皮夹到独立的逻辑性亚帐户。举个反例,一个HD皮夹可能包含两个比特币“账户”:m/44'/0'/0'和m/44'/0'/1'。每位帐户都是它自己亚树的根。

第四层级就是“change”。每一个HD皮夹有两个亚树,一个是拿来接收地址一个是拿来创造变更地址。注意无论以前的层级是否使用是否使用加强衍生,这一层级使用的都是常规衍生。这是为了容许这一层级的树可以在可供不安全环境下,输出扩充的公共锁匙。被HD皮夹衍生的可用的地址是第四层级的子级,就是第五层级的树的“address_index”。例如,第三个层级的主帐户收到比特币支付的地址就是M/44'/0'/0'/0/2。表4-9展示了更多的反例。

表4-9BIP0044HD皮夹结构的反例

HD路径主要描述M/44'/0'/0'/0/2第三个收到公共锁匙的主比特币帐户M/44'/0'/3'/1/14第十五改变地址私钥的第四个比特币帐户m/44'/2'/0'/0/1为了签订交易的在莱特币主帐户的第二个公钥

使用比特币浏览器实验比特币皮夹

根据第3章介绍的使用比特币浏览管理器命令工具,你可以试着生产和延展BIP0032确定性秘钥以及将它们用不同的格式进行展示:

$ sx hd-seed > m # create a new master private key from a seed and store in file "m"
$ cat m # show the master extended private key
96 | Chapter 4: Keys, Addresses, Wallets
xprv9s21ZrQH143K38iQ9Y5p6qoB8C75TE71NfpyQPdfGvzghDt39DHPFpovvtWZaR- gY5uPwV7RpEgHs7cvdgfiSjLjjbuGKGcjRyU7RGGSS8Xa
$ cat m | sx hd-pub 0 # generate the M/0 extended public key xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KE- CeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9
$ cat m | sx hd-priv 0 # generate the m/0 extended private key xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CA- WrUE9i6GoNMKUga5biW6Hx4tws2six3b9c
$ cat m | sx hd-priv 0 | sx hd-to-wif # show the private key of m/0 as a WIF L1pbvV86crAGoDzqmgY85xURkz3c435Z9nirMt52UbnGjYMzKBUN
$ cat m | sx hd-pub 0 | sx hd-to-address # show the bitcoin address of M/0 1CHCnCjgMNb6digimckNQ6TBVcTWBAmPHK
$ cat m | sx hd-priv 0 | sx hd-priv 12 --hard | sx hd-priv 4 # generate m/ 0/12'/4 xprv9yL8ndfdPVeDWJenF18oiHguRUj8jHmVrqqD97YQHeTcR3LCeh53q5PXPkLsy2kRaqgwoS6YZ- BLatRZRyUeAkRPe1kLR1P6Mn7jUrXFquUt