区块链
比特币作为第一个广为人知的数字货币,因其实现了完全匿名的交易,而后被不希望别人知道他做了某种交易的人(比如毒贩)广泛使用。比特币的火爆让技术社区开始注意到比特币底层的一项技术--区块链:这项基于密码学和分布式P2P的技术被认为是第二次互联网革命,我们可以把比特币看做是基于区块链技术而开发的一款虚拟货币。随着区块链技术的成熟,现如今已经诞生了更多区块链技术平台以及基于它的应用。本文将结合现如今流行的区块链技术(比特币、以太坊、hyperledger/fabric)来谈谈密码学在区块链中的应用。
密码学
这里不打算给密码学下一个定义,因为我们生活中实在接触了太多的密码学。比如银行卡密码、加密的网络通信、接头暗号等。现代密码学是建立在复杂的数学理论之上,数学家发现的一系列数学定理保证了密码算法的可靠性。不过这篇文章并不会出现晦涩难懂的数学公式,所以放心的读下去吧。
密码学需要解决的问题主要体现在三个方面:数据机密性、数据完整性、以及认证(用于身份校验)。一个密码学算法通常只能保证某一两个方面,因此实际应用中通常是多个密码算法组合使用以满足我们的需求。
单向散列函数
生活中,“指纹”常用来表明一个特定人的身份。比如刑侦中通过比对犯罪嫌疑人在案发现场留下的指纹信息来确定凶手是否就是犯罪嫌疑人。计算机科学中我们也需要对比两条数据是否一致,但如果两条数据非常大时,一个比特一个比特的比较毫无疑问效率是非常低的。这时我们可以使用单向散列函数先将数据散列运算得到指定长度的字节数然后再通过比对这些散列值来确定数据是否一致。
一个可靠的单向散列函数必须具备以下特性:
- 输入任意长度数据必须输出固定长度的散列值。
- 能够快速计算出散列值(实际场景不允许这个操作花费过多时间)。
- 输入数据有细小差别也要导致散列值差别很大。
- 具备单向性(无法根据散列值反推出原始数据)。
常见的单向散列函数包括MD4/MD5、SHA-1/SHA-256/SHA-384/SHA-512、RIPEMD/RIPEMD-160、以及以Keccak算法作为标准的SHA-3系列函数。其中MD4/MD5、SHA-1、RIPEMD已经存在攻破的算法,不推荐在极其敏感环境下使用。
Keccak算法在2012年经过长达5年的选拔最终成为SHA-3标准,更多关于Keccak算法细节可以浏览这里。
举个简单的例子,如果我们要比较file1 和 file2 文件内容是否一致,怎么办呢?
如上图所示,假如我们使用SHA-256作为我们的散列函数,则伪代码如下:
func equal(file1, file2):
hash1 = sha256(file1)
hash2 = sha256(file2)
return hash1 == hash2
可以看到,我们没有直接去比较两个文件内容是否一致,而是通过比较两个文件的散列值来确定文件内容是否一致(使用了输入数据有细小差别也要导致散列值差别很大这一特性)。那么区块链中又有哪些地方使用了单向散列函数呢?
在区块链中,一系列的交易被矿工打包到区块(Block)中,然后所有区块相连(这里指当前区块的preHash指向上一个区块)便形成了区块链。此基础上结合密码算法和分布式共识算法,便实现了区块链去中心化这一关键特性。
- 单向散列函数作用于区块的连接
上图展示了区块链(包括比特币、以太坊和Fabric)中是如何将区块连接起来的。其中preHash
指的是上一个区块(或区块头)的哈希值(通常使用的是SHA-256算法计算得来)。在需要遍历验证所有区块时,便是通过preHash
值索引到上一个区块直至创始区块。同时,在上图中还有一个值得关注的成员:MRH(Merkle Root Hash)
即默克尔树根节点哈希值。在区块链的每个Block中都存放了一定数量被矿工打包的交易,区块链的交易记录是不容篡改的。而检测区块中的交易是否被篡改便是根据默克尔树根哈希的值前后是否一致来判断。区块链中的默克尔树结构如下:
通过上图可以看到这是一颗典型的二叉树。区块中的每笔交易的哈希值(通过单向散列函数计算得到)两两结合计算出新的哈希值,重复这个过程直到计算出根节点。根节点存放的哈希值被打包到了区块中,当需要验证区块中的一笔交易是否被篡改过时,比如上图中的交易1,只需重新计算交易1的哈希值,然后连同交易2的哈希值最终计算出一个新的根哈希,比较原来的根哈希和新的根哈希是否相等便可以验证交易1是否被篡改过。
这里我们只验证了交易1,相当于对于一个大块数据我们可以只针对其中的一部分进行验证。默克尔树的这个特性被广泛用于P2P资源下载完整性校验中。
单向散列函数在区块链中的应用不仅于此。其他很多地方都使用到了单向散列函数,比如:
- 比特币和以太坊的Pow机制。矿工不断计算给定数据的散列值(之所以这样描述是因为比特币和fabric是计算当前区块头的散列值而以太坊是随机抽取一定数量先前的区块计算散列值),当散列值满足给定的难度策略(difficulty policy)时,便由矿工打包成生成一个新的区块并广播到全网节点。
- 比特币的账户地址。比特币的账户地址为账户签名和执行交易的私钥所对应的公钥,经过SHA-256和RIPEMD160散列,然后再通过Base58Check编码转换成易于阅读的格式得来。
- 伪随机数生成。在生成用户私钥和公钥过程中也需要使用单向散列函数生成随机数。详细细节可以参考这里
使用单向散列函数的地方还有很多,这里不再一一赘述。
后记
密码学在区块链中的运用计划写三篇文章。除去这篇,剩下两篇关于
- 对称加密和非对称加密
- 签名和证书
正在加工中!
参考
- 精通比特币,Andreas•M•Antonopoulos (O'Reilly)。版权2015 Andreas•M•Antonopoulos, 978-1-449-37404-4.
- 图解密码学,(日)结城浩。人民邮电出版社,版权2015
结城浩,ISBN:9787115373625. - 以太坊白皮书,https://github.com/ethereum/wiki/wiki/White-Paper.
版权所有,转载请注明出处。