Files
CategoryResourceRepost/极客时间专栏/左耳听风/区块链/65 | 区块链技术细节:加密和挖矿.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

177 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="65 | 区块链技术细节:加密和挖矿" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/4e/23/4ead5d0450cec7fd2fee063f08915023.mp3"></audio>
前面一篇文章中提到的技术解决了交易信息不能被篡改的问题。但还有一个比较重要的问题,那就是,我们每个人只能发起和自己有关的交易,也就是能发起自己对别人付钱的交易,我们不能发起别人对我付钱,或是别人向别人付钱的交易。
那么,在比特币中是怎么解决这个问题的?让我们先看一些基础的加密技术。
# 比特币的加密方法
## 密钥对/签名/证书
所谓密钥对,也就是一种非对称加密技术。这种技术,在对信息进行加密和解密时,使用两个不同的密钥。这样一来,我们就可以把其中一个密钥公布出去,称之为公钥,另一个密钥私密地保管好,称之为私钥。
现实社会中,有人使用公钥加密,私钥解密,也有反过来用私钥加密,公钥解密,这得看具体的场景。(比特币使用了非对称加密的技术,其使用了[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) 密钥对比技术。)
比如,我把我加密的密钥发布给所有人,然后大家都用这个公钥加密信息,但其他人没有私钥,所以他们解不了密文,只有我能解密文,也只有我能看得懂别人用我的公钥加密后发给我的密文。如下图所示。
<img src="https://static001.geekbang.org/resource/image/ee/71/ee63472f10b0c179a5c3c58d47d9f271.png" alt="" />
但是这会有个问题那就是每个人都有我的公钥别人可以截获Mike发给我的信息然后自己用我的公钥加密一个别的信息伪装成Mike发给我 这样我就被黑了。于是我们需要对Mike的身份进行验证此时就需要用到“数字签名”的概念了。
Mike也有一对密钥对一个公钥给了我私钥自己保留。
<li>
Mike发自己想要的信息做个SHA或MD5的hash得到一个hash串又叫Digest。
</li>
<li>
Mike用自己的私钥把Digest加密得到一段Digest的密文。我们把这个事叫数字签名Signature。
</li>
<li>
然后Mike把他想发给我的信息用我的公钥加密后连同他的数字签名一同发给我。
</li>
<li>
我用我的私钥解密Mike发给我的密文然后用Mike的公钥解密其数字签名得到Digest。然后我用SHA或MD5对解开的密文做Hash。如果结果和Digest一致就说明这个信息是Mike发给我的没有人更改过。
</li>
这个过程如下图所示。
<img src="https://static001.geekbang.org/resource/image/5a/28/5a44ceb1af5a27cc0873cbe4e2571028.png" alt="" />
但是问题还没完。假设有个黑客偷偷地把Jack电脑上的Mike的公钥给换了换成自己的然后截获Mike发出来的信息用自己的密钥加密一段自己的信息以及自己的数字签名。
于是对于Jack来看因为他用了黑客的公钥而不是Mike的那么对他来说他就以为信息来自Mike于是黑客可以用自己的私钥伪装成Mike给Jack通信。反之亦然于是黑客就可以在中间伪装成Jack或Mike来通信这就是中间人攻击。如下图所示。
<img src="https://static001.geekbang.org/resource/image/87/00/876f36ed6a0a617f6356603798f7d700.png" alt="" />
这个时候就比较麻烦了。Mike看到有人在伪造他的公钥想了想他只能和Jack找了个大家都相信的永不作恶的权威的可信机构来认证他的公钥。这个权威机构用自己的私钥把Mike的公钥和其相关信息一起加密生成一个证书。
此时Jack就可以放心地使用这个权威机构的证书了。Mike只需要在发布其信息的时候放上这个权威机构发的数字证书然后Jack用这个权威机构的公钥解密这个证书得到Mike的公钥再用Mike的公钥来验证Mike的数字签名。
<img src="https://static001.geekbang.org/resource/image/bb/57/bb3a47bf0b8c84a6c85d864c88739357.png" alt="" />
上面就是整个密钥对、签名和证书的全部基础细节。比特币也用了这样的基础技术来认证用户的身份的。下面,我们来看看比特币的一些细节。
## 比特币的加密
在比特币的世界里每一笔交易的From和To都是每个用户的公钥Public Key。也就是说使用用户的公钥来做交易的账户。于是这个过程很简单。
<li>
交易的发起方只能是支付方,支付方需要用自己的私钥来加密交易信息并制作相关的交易签名。
</li>
<li>
网络上其他人会用你的公钥(也就是交易的支出方)来做解密来验证。
</li>
为什么不需要那个证书机构呢?不怕中间人攻击吗?这是因为,如果黑客想要伪造一笔别人的交易,那么他需要换掉半数以上结点上的被攻击者的公钥,这不太现实。与其这样做,还不如去偷被攻击者的私钥,可能还简单一些。
下面是一个交易链的图示。这个交易链的钱从A -&gt; B -&gt; C -&gt; D一共3笔交易。
<img src="https://static001.geekbang.org/resource/image/fe/a8/feaaa557eab454dd1678415da7f554a8.png" alt="" />
图片来源:[Ken Shirriff Blog](http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html)
<li>
**发起交易**。我们从第一笔交易可以看到A用自己的私钥为交易信息和自己的地址生成了交易的签名然后把交易信息、自己的地址、交易签名和自己的公钥放出去这样方便别人来验证的确是A发起的。
</li>
<li>
**验证交易**。在验证时使用A的公钥解密交易签名得到交易的hash值。把交易信息和自己的地址做hash看看是不是和签名解密后的hash值一致。
</li>
这里需要注意一个细节比特币的地址是由我们的公钥生成的生成规则比较复杂可以参看Bitcoin的Wiki页 - [Technical background of version 1 Bitcoin addresses](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses)。
# 比特币的挖矿
前面说到在比特币的区块hash算法中要确保下面这个公式成立
```
SHA-256(SHA-256 (Block Header)) &lt; Target
```
而在区块头中可以完全自由修改的只有一个字段就是Nonce其他的Timestamp可以在特定范围内修改Merkle Root和你需要记录的交易信息有关系所有的矿工可以自由地从待确认交易列表中挑选自己想要的交易打包
所以基本上来说你要找到某个数字让整个hash值小于Target。这个Target是一个数**其决定了我们计算出来的hash值的字符串最前面有几个零**。我们知道hash值本身就是一串相对比较随机的字符串。但是要让这个随机的字符串有规律是一件很困难的事除了使用暴力破解没有其他办法。在计算机世界里我们把这个事叫&quot;哈希碰撞&quot;(hash collision)碰撞前几个位都是0的哈希值。
下面是一个示例。我想找到一个数,其和&quot;ChenHao&quot;加起来被hash后的值前面有5个零。
测试程序如下:
```
import hashlib
data=&quot;ChenHao&quot;
n=1
while n &lt; 2**32:
str = data + `n`
hash = hashlib.sha256(str).hexdigest()
hash = hashlib.sha256(hash).hexdigest()
if hash.startswith('00000'):
print str, hash
break
n = n + 1
```
这是一个暴力破解的算法。这个程序在我的MacBook Pro上基本要10秒钟才跑得出来结果。
找到1192481时找到了第一个解如下所示
```
ChenHao1192481
00000669e0eeb33ee5dbb672d3bd2deb0c32ef9879ef260f0debbdcb80121160
```
那么控制前面有多个0的那个Target又是怎么来的呢是由Bits这个字段控制的也就是难度系数前面需要的0越多难度也就越大。其中的算法你可以看一下Bitcoin的Wiki上的[Difficulty词条](https://en.bitcoin.it/wiki/Difficulty),这里我就不多说了。
**这个难度系数会在每出2016个区块后就调整一次。现在这个难度是要在前面找到有18个零。如下所示(一个真实的区块链的Hash值)**
[000000000000000000424118cc80622cb26c07b69fbe2bdafe57fea7d5f59d68](https://blockchain.info/block/000000000000000000424118cc80622cb26c07b69fbe2bdafe57fea7d5f59d68)
**一个SHA-256算法算出来的哈希值有 $2^{256}$ 种可能性而前面有18个零意味着前面有72个bits是零。于是满足条件的哈希值是有$2^{184}$种可能性,概率是$\frac{1}{2^{72}}$ **
是的很有可能你穷举完Nonce后还找不到那就只能调整Timestamp和Merkle Root调整不同的记账交易了。
所以,一般的挖矿流程如下。
<li>
从网络上取得之前的区块信息。
</li>
<li>
&quot;待记账区&quot;中获取一组交易数据(有优先级,比如成长时间、矿工小费等)。
</li>
<li>
形成区块头计算Merkle Root并设计记账时间Timestamp等
</li>
<li>
开始穷举Nonce来计算区块头的hash值。如果前面有18个零小于Target那么记账成功。如果没有则从第一步重新开始。
</li>
<li>
一旦某矿工成功打包一个区块,他就会告诉其他矿工。收到消息的矿工会停下手上的工作,开始验证,验证通过后,广播给其他矿工。
</li>
所以满足条件的这个难度系数成为了挖矿的关键。设置这个难度系数就是为了让全网产生的区域名平均在10分钟一块。而根据比特币无中心服务器的架构也就是其挖矿的机器数量是想来就来想走就走的计算力可能会不一样。因此为了保证每10分钟产生一个区块当算力不足的时候难度下降当算力充足的时候难度提高。
今天的这18个零基本上来说一般的电脑和服务器就不用想了必须要算力非常非常高的机器才能搞定。所以在今天挖矿这个事已经不是一般老百姓能玩的了。
下图展示了整个比特币的难度历史。
<img src="https://static001.geekbang.org/resource/image/4d/14/4d7e09ee0c03a807c1c5326d0d5c2e14.png" alt="" /><br />
(图片来源:[http://bitcoin.sipa.be](http://bitcoin.sipa.be)
上面这个图只是算力的表现,可能并不直观。我们还是用其耗电量来说可能会更好一些。根据&quot;Bitcoin Energy Consumption Index&quot;统计,截至 2017年11 月 20 日,比特币过去一年挖矿的电力总消耗已累计达 29.51 TWh1TWh = $10^{12}$ Wh约占全球总电力消耗的 0.13%。该数字甚至已经超过近 160 个国家或地区一年的电力消耗,包含冰岛和尼日利亚。若全球的比特币矿工自成一国,该国的电力消耗排名可排到全球第 61 名。
看到这里,你一定要问,为什么要挖矿呢,不就是记个账呗。为了系统地说明这个问题,我们下面来看看去中心化的共识机制。
文末给出了《区块链技术》系列文章的目录,希望这一系列内容对你有启发,有帮助。
- [区块链的革命性及技术概要](https://time.geekbang.org/column/article/5197)
- [区块链技术细节:哈希算法](https://time.geekbang.org/column/article/5363)
- [区块链技术细节:加密和挖矿](https://time.geekbang.org/column/article/5438)
- [去中心化的共识机制](https://time.geekbang.org/column/article/5612)
- [智能合约](https://time.geekbang.org/column/article/5623)
- [传统金融和虚拟货币](https://time.geekbang.org/column/article/5636)