这篇文章带来ECE111第十节课的Slides以及自己的一些补充。
该课程的网站如下:
https://link.zhihu.com/?target=http%3A//cwcserv.ucsd.edu/~billlin/classes/ECE111/index.php
最近由于工作比较忙加上有点杂事,一直没有更新。SHA256的代码我已经写完了,目前在优化,相关的文章讲解代码也正在写。请大家稍微等待一段时间。
这节课的内容是SHA256的升级,比特币中的加密。实际上用的仍然是SHA256。关于这个内容,也有相关的Project,跟SHA256区别不大,我就不再单独进行代码实现了。读者如果理解了SHA256应该可以很轻松地自行写出来。接下来让我们进入主题:
所谓的区块链是一个不断增长的全网总账本,区块链是一个一个的区块构成的有序链表,每一个区块都记录了一系列的交易,并且每个区块都指向前面一个区块,从而形成一个链表。
每个区块都有一个唯一的哈希标志,同时区块通过记录上一个区块的哈希来指向上一个区块。
比特币的每一个区块都有一个header,header中存储了很多项关于区块的关键信息,主要包含以下几项:
- Version,区块的版本号。
- 之前一个区块的header哈希
- Merkle根哈希。用来确保该区块的所有交易记录无法被篡改。由于这个哈希是由区块中包含的所有交易的哈希值运算得出的,如果有人篡改了任何交易,这个哈希值就会变化。header 中保留了这个值意味着只要 header 安全了,整个区块就安全了,这解释了为何计算 nouce 的时候,只需要计算 header 的哈希,而忽略区块主体数据。至于更详细的解释,请参考这篇文章:区块链原理
- 时间,精确到秒
- 压缩格式的target值
- Nonce,一个32bit的数据
我们对整个header进行哈希运算,运算的过程中,Nonce会逐渐增加,直到找到能够使区块哈希小于target的nonce。target和SHA256的结果都是256bit。
如图所示,比特币哈希可以分为两次运算。之所以分两次,是为了缓解长度扩展攻击(具体原理我也不懂)。
第一次是将上述的header,共640bit扩展成1024bit。即两个Block,完成第一次SHA256运算。然后将运算得到的结果共256bit扩展成512bit再进行一次SHA256运算。用运算表达式表达即为 ���ℎ(���ℎ(ℎ�����))
通过持续增加Nonce,直到计算得到的哈希值小于target。
之所以这么做,是因为哈希运算的值是没有具体规律的,仅仅改变输入值的某一个比特,输出值叶可能千差万别。因此这种运算要求前缀全部是0,挖矿的人必须进行大规模的运算才能达到该目标。没有特定的输入技巧
题目的要求比较简单,只需要运算16组header即可。nonce从0一直递增到15。同时也不用检查输出的结果是否小于taget。
一个比较关键的优化点,由于输入的header是640bit,扩展成1024bit则为两个Block。对于不同的nonce而言,第一个512bit是一样的,因此对于这一部分而言,只需要计算一次即可。
我们总共可以划分为三个阶段
- 阶段一:先对第一个block进行SHA256运算。初始的H0~H7为固定值,Wt和这个固定的512bit相关。
- 阶段二:初始的H0~H7为第一个Block的运算结果最终值。Wt和第二个Block的512bit相关,这512bit为剩余的96bit固定,32bit的nonce,填充1bit的1,63bit的0,再填充32'd640(原始数据长度)
- 阶段三:计算第二次SHA256。初始的H0~H7为固定值,Wt为阶段二运算得到的H0~H7,1bit的1,223bit的0,32'd256。
需要注意的是,阶段一和阶段二是一次SHA256运算,不是两次!只不过有两个block而已。区别是不是同一次SHA256运算,关键在于H0~H7有没有初始化。
最终我们完成16个header的运算,题目只要求我们写回第一个header的运算值