BTC私钥和地址

比特币基于密码学的,密码学是由数学分支出来的,在计算机安全领域被广泛使用.密码学在希腊语中是“秘密写作”的意思,但密码学这门学科不仅仅只有秘密写作,还包括加密技术。密码学可以用于不泄露秘密(数字签名),就能证明知晓加密的内容,或证明数据的真实性(数字指纹)。这些类型的密码学证明是比特币中至关重要的数学工具,并被广泛用于比特币应用。有趣的是,加密不是比特币的重要组成部分,因为它的通信和交易数据没有加密,也不需要加密来保护资金。

比特币的所有权是通过数字密钥、比特币地址和数字签名来确定的。数字密钥实际上并不存储在网络中,而是由用户生成之后,存储在一个叫做钱包的文件或简单的数据库中。用户钱包中的数字密钥完全独立于比特币协议,可由用户的钱包软件生成并管理,而无需参照区块链或访问互联网。密钥实现了比特币的许多有趣特性,包括去中心化信任和控制、所有权认证和基于密码学证明的安全模型。

密钥是成对出现的,由私钥和公钥所组成。公钥就像银行的帐号,而私钥就像PIN码或支票的签名。比特币的用户很少会直接看到数字密钥。一般情况下,它们存储在钱包文件内,由比特币钱包软件进行管理。

私钥和公钥

一个比特币钱包中包含一系列的密钥对,每个密钥对包括一个私钥和一个公钥。私钥(k)是一个数字,通常是随机选出的。基于私钥,我们就可以使用椭圆曲线乘法这个单向密码函数产生一个公钥(K)。基于公钥(K),我们就可以使用一个单向密码哈希函数生成比特币地址(A)。我们将从生成私钥开始,讲述如何使用椭圆曲线运算将私钥生成公钥,并最终由公钥生成比特币地址。 私钥、公钥和比特币地址之间的关系如下: btc-head

为什么使用非对称密码技术(公钥/私钥)?

为什么在比特币中使用非对称密码技术?它不是用于对交易进行“加密”(保密)的。 相反,非对称密码技术的最有用特性是生成数字签名。可以将私钥用作交易的数字指纹来产生数字签名。 该签名只能由知晓私钥的人生成。 但是,任何访问公钥和交易指纹的人都可以验证签名。 这种非对称密码学的适用性使得任何人都可以验证每笔交易的每个签名,并且确保只有私钥的所有者可以生成有效的签名。

私钥

私钥就是一个随机选出的数字而已。拥有和控制了私钥,就相当于控制了该私钥对应的比特币地址中的所有资金。通过证明比特币交易中资金的所有权,私钥可以生成花费该笔资金的签名。私钥任何情况下都必须保密,因为一旦被泄露给第三方,相当于该私钥保护之下的比特币也拱手相让了。私钥还必须进行备份,以防意外丢失,因为私钥一旦丢失就无法恢复,其所保护的比特币也将永远丢失。

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

从一个随机数生成私钥 生成密钥的第一步也是最重要的一步,是要找到足够安全的熵源,即随机性来源。生成一个比特币私钥在本质上与“在1到2256之间选一个数字”无异。只要选取的结果是不可预测或不可重复的,那么选取数字的具体方法并不重要。比特币软件使用操作系统底层的随机数生成器来产生256位的熵(随机性)。通常情况下,操作系统随机数生成器由人工的随机源进行初始化,这就是为什么也可能需要不停晃动鼠标几秒钟。

更准确地说,私钥可以是1和n-1之间的任何数字,其中n是一个常数(n=1.158 * 10^77,略小于2^256),并被定义为由比特币所使用的椭圆曲线的阶(见下面的椭圆曲线密码学解释这一节)。要生成这样的一个私钥,我们随机选择一个256位的数字,并检查它是否小于n-1。从编程的角度来看,一般是通过在一个密码学安全的随机源中取出一长串随机字节,对其使用SHA256哈希算法进行运算,这样就可以方便地产生一个256位的数字。如果运算结果小于n,我们就有了一个合适的私钥。否则,我们就用另一个随机数再重复一次。

警告 不要自己写代码来生成随机数,也不要使用编程语言提供的简易随机数生成器来获得一个随机数。使用密码学安全的伪随机数生成器(CSPRNG),并且需要有一个熵源值足够的的种子。使用随机数发生器的程序库时,需仔细研读其文档,以确保它是密码学安全的。正确实施CSPRNG是密钥安全性的关键所在。

公钥

通过椭圆曲线乘法可以从私钥计算得到公钥,这是不可逆转的过程:K = k G 。其中 k 是私钥,G 是被称为生成点的常数点,而 K 是所得公钥。其反向运算,被称为“寻找离散对数”——已知公钥K来求出私钥k——是非常困难的,就像去尝试所有可能的k*值,即暴力搜索。在演示如何从私钥生成公钥之前,我们先稍微详细学习下椭圆曲线密码算法。

提示 椭圆曲线乘法是密码学家称之为“陷阱门”的一种函数:在一个方向(乘法)很容易计算,而在相反的方向(除法)是不可能计算出来的。私钥的所有者可以容易地创建公钥,然后与世界共享,知道没有人可以从公钥反转该函数计算出私钥。 这个数学技巧成为证明比特币资金所有权不可伪造和安全的数字签名的基础。

生成公钥

以一个随机生成的私钥k为起点,将其乘以曲线上一个预定的点,叫做生成点G得到曲线上的另一点,这就是相应的公钥 K。生成点是secp256k1标准的一部分,比特币密钥的生成点都是相同的:

{K = k * G}

其中k是私钥,G是生成点,在该曲线上所得的点K是公钥。因为所有比特币用户的生成点是相同的,一个私钥k乘以G将得到相同的公钥K。k和K之间的关系是固定的,但只能单向运算,即从k得到K。这就是可以把比特币地址(K的衍生) 与任何人共享而不会泄露私钥(k)的原因。

提示 因为其中的数学运算是单向的,所以私钥可以转换为公钥,但公钥不能转换回私钥。

实现了椭圆曲线乘法,我们用之前产生的私钥k和与生成点G相乘得到公钥K:

K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G

比特币地址

比特币地址是一个由数字和字母组成的字符串,可以展示给任何给你转账比特币的人。由公钥(一个同样由数字和字母组成的字符串)生成的比特币地址以数字“1”开头。下面是一个比特币地址的例子:

1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

在交易中,比特币地址通常作为资金接受者地址。如果把比特币交易比作一张支票,比特币地址就是收益人,也就是写入“支付给谁”一栏的内容。一张支票的收款人可能是某个银行账户,也可能是某个公司、机构,甚至是现金支票。由于支票不需要指定一个特定的账户,而是用一个抽象的名字作为收款人,这就使它成为一种相当灵活的支付工具。与此类似,比特币交易使用类似的抽象:比特币地址,这就使比特币交易变得很灵活。比特币地址代表一对公钥和私钥的所有者,也可以代表其它东西,

比特币地址可由公钥经过单向哈希算法得到。密码学哈希算法是一种单向函数,接收任意长度的输入产生指纹或哈希。哈希函数在比特币中被广泛使用 :比特币地址、脚本地址以及在挖矿中的工作量证明算法。由公钥生成比特币地址时使用的算法是Secure Hash Algorithm (SHA)和the RACE Integ rity Primitives Evaluation Message Digest (RIPEMD),具体来说是SHA256和RIPEMD160。 以公钥 K 为输入,计算其SHA256哈希值,并以此结果计算RIPEMD160 哈希值,得到一个长度为160位(20字节)的数字:

A = RIPEMD160(SHA256(K))

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

提示 比特币地址与公钥并不不同。比特币地址是公钥经过单向的哈希函数生成的。

通常用户见到的比特币地址是经过“Base58Check”编码的,这种编码使用了58个字符(Base58数字系统)和校验码,提高了可读性、避免歧义并有效防止了在地址转录和输入中产生的错误。Base58Check编码也被用于比特币的其它地方,例如比特币地址、私钥、加密的密钥和脚本哈希中,用来提高可读性和录入的正确性。下一节中我们会详细解释Base58Check的编码和解码机制,以及它产生的结果。

下图描述了如何从公钥生成比特币地址: btc-head

Base58和Base58Check编码

为了更简洁方便地表示长串的数字,使用更少的符号,许多计算机系统在表示大于十进制时,会使用数字和字母混合组成。例如,传统的十进制计数系统使用0-9十个数字,而十六进制系统使用了16个,增加了 A-F 六个字母来表示0-9额外的符号。一个同样的数字,它的十六进制表示就会比等值得十进制表示更短。更为简洁的是,Base64使用了26个小写字母、26个大写字母、10个数字以及两个符号(例 如“+”和“/”),用于在像电子邮件这样的文本媒介中传输二进制数据。Base64通常用于邮件中添加二进制附件。Base58 是一种基于文本的二进制编码格式,用在比特币和其它的密码货币中。这种编码格式提供了紧凑表示,易读性,错误检测预防这几方面彼此之间的平衡。Base58是Base64编码格式的子集,同样使用大小写字母和10个数字,但舍弃了一些容易读错和在特定字体中外观容易混淆的字符。具体地,Base58不含Base64中的0(数字0)、O(大写字母o)、l(小写字母 L)、I(大写字母i),以及“+”和“/”两个字符。简而言之,Base58就是由不包括(0,O,l,I)的大小写字母和数字组成。 下面是base58字母表 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

为了增加防止打印和转录错误的安全性,比特币常用的是Base58Check,它是一种内置错误校验代码的Base58编码格式。检验和是额外4个字节,被添加到正在编码的数据末端。校验和是从编码的数据的哈希值中得到的,所以可以用来检测并避免转录和输入中产生的错误。使用Base58check编码时,解码软件会计算数据的校验和并和编码中自带的校验和进行对比。二者不匹配则表明有错误产生,这个Base58Check的数据就是无效的。这就防止输错的比特币地址被钱包软件认为是有效的地址,造成资金的丢失。

为了将数据(数字)转换成Base58Check格式,首先我们要对数据添加一个称作“版本字节”的前缀,这个前缀用来识别编码的数据的类型。例如,比特币地址的前缀是0(十六进制是0x00),而编码私钥的前缀是128(十六进制是0x80)

接下来,我们计算“双哈希”校验码,意味着要对之前的结果(前缀和数据)运行两次SHA256哈希算法:

checksum = SHA256(SHA256(prefix+data))

在产生的长度为32个字节的哈希值(两次哈希运算)中,我们只取前4个字节。这4个字节就作为检验错误的代码或者校验码。将校验码添加到最后。 结果由三部分组成:前缀数据校验码。这个结果采用之前描述的Base58字母表编码。下图描述了Base58Check编码的过程。

btc-head Base58Check版本前缀和编码后的结果:

Type Version prefix (hex) Base58 result prefix
Bitcoin Address 0x00 1
Pay-to-Script-Hash Address 0x05 3
Bitcoin Testnet Address 0x6F m or n
Private Key WIF 0x80 5, K, or L
BIP-38 Encrypted Private Key 0x0142 6P
BIP-32 Extended Public Key 0x0488B21E xpub

私钥的格式

公钥和私钥都可以有多种格式。虽然看起来可能不同,但是所编码的是同样的数字。这些不同的编码格式主要是用来方便人们无误地阅读和抄写。 私钥的格式有许多,所有这些都对应于相同的256位的数字。表4-2展示了私钥的三种常见格式。不同的格式用在不同的场景。十六进制和原始的二进制格式用在软件的内部,很少展示给用户看。WIF格式用在钱包之间密钥的输入和输出,也用于代表私钥的二维码(条形码) 私钥形式(编码格式)

Type Prefix Description
Raw None 32 bytes
Hex None 64 hexadecimal digits
WIF 5 Base58Check encoding: Base58 with version prefix of 128- and 32-bit checksum
WIF-compressed K or L As above, with added suffix 0x01 before encoding

如下,相同的私钥,不同的私钥: | Format |Private key| | ————- | —- | | Hex | 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd | |WIF | 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn| |WIF-compressed | KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ|

这些格式都表示相同的数字,相同的私钥。虽然编码后的字符串看起来不同,但任何一种格式都能很容易转换为其他格式