揭秘比特币和区块链(三):比特币的私钥、公钥与地址 [zz]
原文转自:InfoQ
地址、交易、区块、网络是区块链数据里面最基本最重要的概念。地址用来标示一笔交易的支出方和接收方。所有的交易最终需要被记到统一的账本——区块链上,而这个账本是通过区块确认并完成的。每一个新区块,都会被打上时间戳,最终生成依照时间前后排列并加以记录。每个独立节点之间又通过比特币网络来建立联系,这样就为电子交易记录建立了一个去中心化、分布式的时间戳服务器系统。
很复杂,在这一节,我们先讲地址。
公钥密码学
讲到地址,我们就不得不先说一说密码学,作为保护信息传输安全的技术手段,密码在人类社会中的应用源远流长,凯撒密码是古典密码的典型代表,它的基本思想是通过字符的代换来实现加解密。因此古典密码的安全性主要依赖加密算法本身的安全性,如果算法泄露了,要加密的信息也就没有秘密可言了。
如今密码学相关技术已经深入各个领域,它们的理论共识都遵循由奥古斯特•柯克霍夫在19世纪提出“柯克霍夫原则”—— 密码系统应该即使被所有人知道其运作步骤,仍然是安全的。即算法是公开的,唯一需要保护的是密钥。
1949年香农发表了《保密系统的信息理论》,为对称密码系统建立了理论基础,带来了加密传输基于秘钥安全而不是基于加密算法安全的理论和技术变革。这是密码学发展的里程碑,标志着现代密码学时代的来临。
公钥密码学兴起之前,对称加密是主流的加密模式,人们基于秘钥来对信息进行加解密,通常情况下,密钥越长,代表着密文被破解的难度越大。由于加密算法和解密算法都是同一模式,只有一把密钥保证加密数据的安全,因此这种加密算法也叫做“对称加密算法”。对称加密有一个最大弱点:甲方必须把密钥告诉乙方,否则乙方无法解密。而保存和传递密钥,就成了最头疼的问题。
公钥密码学是现代密码学最重要的进展。公钥密码学可以在不直接传递密钥的情况下,完成密文的解密。加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,系统的安全性既不依赖算法的保密,也不用直接传递密钥。基于这种公钥机制的思想,开始出现了一系列非对称加密算法。
1976年Whitfield Diffie & Martin Hellman首次提出了基于数学难题的公钥密码机制,1978年RSA公钥密码机制的出现,成为公钥密码的杰出代表并成为事实标准,在密码学史上创造了又一个新的里程碑。90年代公钥密码学进一步发展,基于椭圆曲线乘法、素数幂等数学函数的公钥算法诞生,使得数字密钥和不可伪造的数字签名成为可能。
数据签名算法的核心在于证明数据的发送方是签名者发出的、不可抵赖,而不是待签名数据的保密性。
下图比较说明非对称加密与对称加密算法的区别:
非对称加密需要两个(一对)密钥:公开密钥(publickey)和私有密钥(privatekey),用公钥对数据进行加密后,只有对应的私钥才能解密;反之如果私钥用于加密,则只有对应的公钥才能解密。通信双方无须交换密钥就可以建立保密通信。
公钥算法用到的是私钥与公钥,他们和比特币体系中常常说到的地址有什么关系?在比特币系统中,私钥由32字节的随机数组成,通过私钥可以算出公钥,公钥经过一系列哈希及编码算法就得到了比特币中的地址。所以地址其实是公钥的另一种表现形式,可以理解为公钥的摘要。
相关的加密算法
在私钥、公钥及地址的相关运算中,用到了基于secp256k1椭圆曲线乘法的签名算法、SHA-256、RIPEMD-160,和Base58编码。
椭圆曲线签名算法
椭圆曲线在密码学中的使用是在1985年由Neal Koblitz和Victor Miller分别独立提出的。它的主要优势是在某些情况下它比其他的算法(比如RSA)使用更小的密钥但提供相当的或更高等级的安全性。
比特币使用了基于secp256k1椭圆曲线数学的公钥密码学算法。它包含私钥与公钥,私钥用于对交易进行签名,将签名与原始数据发送给整个比特币网络,公钥则用于整个网络中的节点对交易有效性进行验证。签名算法保证了交易是由拥有对应私钥的人所发出的。
哈希函数
SHA-256是一种哈希函数,已经在上一节的讲解中做了介绍,这里不再赘述[1]。
RIPEMD-160也是在生成地址时用到的一种哈希函数,其输出长度为20字节(160位)。比特币用它减少标识接收方的字节数。
Base58编码
可读性编码算法,类似古典密码学里的置换算法,理论上并不是密码学理论的核心内容。可读性编码算法不是为了保护数据的安全性,而是为了可读性。以二进制进行传输的信息是不具备可读性的,数字与字母组成的字符串才更容易被识别。可读性编码不改变信息内容,只改变信息内容的表现形式(部分编码算法还加入了容错校验功能,以保证传输过程中数据的准确性和完整性)。
Base64是常见的可读性编码算法,所谓Base64,即是说在编码过程中使用了64种字符:大写A到Z、小写a到z、数字0到9、“+”和“/”。
Base58是Bitcoin中使用的一种编码方式,主要用于产生Bitcoin的钱包地址。相比Base64,Base58不使用数字”0”,字母大写”O”,字母大写”I”,和字母小写”i”,以及”+”和”/”符号。
设计Base58主要的目的是:
- 避免混淆。在某些字体下,数字0和字母大写O,以及字母大写I和字母小写l会非常相似。
- 不使用"+"和"/"的原因是,非字母或数字的字符串难以作为账号的一部分被接受。
- 没有标点符号,通常不会被从中间分行。
- 使大部分的软件支持双击选择整个字符串。
比特币中使用Base58算法来对公钥的Hash160及私钥进行编码,以生成以1或3开头的比特币地址及WIF(Wallet import Format)格式的私钥。
私钥与公钥
比特币私钥其实是使用SHA-256生成的32字节(256位)的随机数,有效私钥的范围则取决于比特币使用的secp256k1 椭圆曲线数字签名标准。大小介于0x1 到0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140之间的数几乎都是合法的私钥。
在私钥的前面加上版本号,后面添加压缩标志和附加校验码,(所谓附加校验码,就是对私钥经过2次SHA-256运算,取两次哈希结果的前四字节),然后再对其进行Base58编码,就可以得到我们常见的WIF(Wallet import Format)格式的私钥。
私钥经过椭圆曲线乘法运算,可以得到公钥。公钥是椭圆曲线上的点,并具有x和y坐标。公钥有两种形式:压缩的与非压缩的。早期比特币均使用非压缩公钥,现在大部分客户端默认使用压缩公钥。
由于数学原理,从私钥推算公钥是可行的,从公钥逆推私钥是不可能的。
初识比特币的人常有一种误解,认为比特币公钥就是地址,这是不正确的。从公钥到地址还要经过一些运算。
地址的生成
椭圆曲线算法生成的公钥信息比较长,压缩格式的有33字节,非压缩的则有65字节。地址是为了减少接收方所需标识的字节数。比特币地址的生成步骤如下:
- 生成私钥与公钥
- 将公钥通过SHA256哈希算法处理得到32字节的哈希值
- 后对得到的哈希值通过RIPEMD-160算法来得到20字节的哈希值 —— Hash160
- 把版本号[2]+Hash160组成的21字节数组进行双次`256哈希运算,得到的哈希值的头4个字节作为校验和,放置21字节数组的末尾。
- 对组成25位数组进行Base58编码,就得到地址。
下图以非压缩格式的65字节公钥示意上述过程:
由于椭圆曲线乘法以及哈希函数的特性,我们可以从私钥推导出公钥,也可以从公钥推导出地址,而这个过程是不可逆的。也正因如此,在整个比特币系统中,私钥是最关键的部分。私钥泄露也就意味着丢失了一切。
我们要花掉一个地址上的资产,需要构造一笔交易,同时使用这个地址对应的私钥签名。而如果我们要将资产转移到某个地址上,只需要转账给他公开的地址就行了。
在下一节,我们将详细讲述比特币交易是如何构成和实现的。
[1] http://www.infoq.com/cn/articles/bitcoin-and-block-chain-part02
[2] 普通地址P2PKH的版本默认值是0,P2SH类型的地址版本默认值是5