好的HASH算法有什么特点?
注意HASH算法有很多,比如MD5、SHA-1、SHA-2等,再如BTC用的SHA-256和RIPEMD-160等。
至少有这么两个特点:
1、对于任意两个不同的输入,应该产生不同的输出。(这叫抗碰撞)
2、正向计算很容易,反过来从输出倒推输入,就非常难,只能靠暴力猜。(这叫不可逆)
先看第一个特点:抗碰撞
一个好的HASH算法,对于任意两个不同的输入,应该产生不同的输出。
事实证明,MD5、SHA-1不能算很好的HASH算法,因为王小云院士等人,已经可以找到两个不同的输入,产生相同的HASH输出。具体可以看看相关文章1、2。
如何形象理解这个特点呢?
首先,这个HASH算法的输出必须要有一定的长度,如果长度不够,肯定会有重复的。比如假设一个HASH算法,输出只有1位,输出不是0就是1,那是不是运行两、三次,就能找到了不同输入相同输出了呢!如果输出只有两位,这个HASH的输出就只有4种可能,00、01、10、11,那是不是运行四、五次,就能找到不同输入相同输出了呢!
所以MD5有128位这么长,SHA-256有256位这么长!
其次,要保障HASH值是非常随机、非常均匀地落在整个输出空间上。而且输入有一点点的不同,输出都会全然的不同。
这样,就有了一种ID的效果,HASH就像是每个输入各异的“指纹”。比如,你把1000万份不同的文件都做了HASH,每份文件都获得一个独一无二的HASH值,就可以把这个当作是一个文件的ID。每个ID都指代了一个独一无二的文件,如果再遇到ID相同的,就表明遇到相同的文件了。
再次,要能理解,输出的空间是非常大的。
对于像RSA-256这样的算法,其输出位数为256位,那么可能的值就会有10^78个(也即2^256个),这是多么大的一个数呢?
全地球沙子的数量(不只是海滩上的,而是所有),有人估算过,大致是7*10^21个,还不到10^22个。
全宇宙星球的数量,也大致不过7*10^22个,还不到10^23个。
你给它两个不同的输入,它产生相同输出的概率,比下面这个例子中的概率还要小得多:
你随便在一个星球上选了一粒沙子,另外一个人,在完全不受你影响的情况下,也随机在某个星球上随机选了一粒沙子,结果你俩选择了同一粒沙子!然后你俩还不约而同地选择了这个沙子中的同一个原子!
现在看第二个特点:不可逆
一个好的HASH算法,要求正向计算很快,但反向几乎不可能。
比如,我现在有一个BTC私钥,形如:
5HvrDrdQ9EpJTcJHXuctU9vUjydzuZ1????????????????DCHa
为了保密,我把其中16个字符用?代替。
计算出这个私钥的MD5值为:
630a0cec43d49095027b224ea0f2b317
那么,请问,全世界的黑客,有没有能力通过破解MD5,得到我这个私钥呢?
答案是:按照现在的能力,不能。
黑客的做法,只能是,不断尝试这16个?号可能的组合,计算其MD5值,以期有一天能算出相同的MD5值。
但这种暴力猜解需要很长时间。(大致毛估一下,以目前的技术,如果全世界黑客联合起来,拥有类比全球BTC挖矿那么大的算力,那也至少要算5年。)
那么,挖矿是在干什么
2021年6月13日18:09:30,BTC矿工们挖出一个HASH:
00000000000000000009813c8a3b95e3a75d878419547b7fe4dd71f9dc71da72
看看这个HASH多么漂亮!它的前面有多少个0!
上面是用16进制表示的,所以,每个0其实是二进制的0000,所以上面那个HASH,前面是19*4=76个二进制的0!
这个HASH是一个区块的HASH(严格的说,是这个区块头部的HASH)。
最近每10分钟就出一个这么漂亮的。
矿工们做了多少次HASH才做出这么漂亮个HASH呢?
不知道,反正平均2^76次才会出现一个这样的,你说做了多少次呢。
他们这么费劲挖这个,图啥呢?
图这个区块奖励的BTC。
挖出这个区块的矿工(可能是很多人一起挖的),得到了6.54164549个BTC,其中6.25个是系统奖励的,剩下的是赚的手续费。
哦,我大致明白HASH了,区块又是什么?
现在给大家讲讲区块链的老祖宗—BTC—的工作原理。
如果一遍看不懂,就看两遍,两遍看不懂,就大声读第三遍。
一般都能读懂。
1、互联网中若干个节点(节点就是计算机啦!)同时运行BTC软件。这些软件是开源的,谁都可以下载了来运行(本文说的节点是指全功能节点,全球目前大约有1000个左右)。
2、人们如果要发起BTC转账(也即交易),就让某个节点在互联网广播转账信息,此交易很快传遍全网每个节点。每个节点都会检查它所收到的交易是否符合逻辑(比如有没有那么多钱来转账),如果不对,就会把这个交易抛弃掉。
转账就是:张三给李四发送1个BTC,王五给赵六发送0.1个BTC,诸如此类。差不多就是这个意思,每一笔转账也叫一个交易。
3、平均每隔一段时间(平均10分钟),网内某个节点就会率先打包出一个区块,区块里面含有这段时间的所有交易数据,这个区块会广播到全网,每个节点都会收到该区块(大小在1M左右)。
3a:打包是有条件的,这个区块的头部的HASH值必须很好看。
3b:平均10分钟才出一个,这是由挖矿难度导致的。难度是动态调整的,每两周调整一次,调整使得全网平均每10分钟才能挖出一个区块。
在一个完全去中心化的网络中,难度调整是如何做到的呢?方法是:每过2016个区块,所有节点都会自发地调整难度(写在代码里了)。新的难度是由最近2016个区块的花费时长与20160分钟(两周)比较后调整得出的。如果花费时间短于20160分钟,就将难度调大一些,反之亦然则调小一些。难度可以简单地理解为要求HASH值前面有多少个0。
3c:每个10分钟内,世界上都会发生很多笔交易,这些交易都等着打包(最终只有打包在区块里的交易才被人们承认)。每个试图打包的矿工,把自己收到的、尚未打包的交易,放在区块里(由于区块大小的限制,平均一个区块能装大约2000多个交易),然后通过填充区块中的随机数区域,计算HASH,以期找到一个好看的HASH(符合难度就叫好看),找到了就叫打包成功(也就是挖矿成功),赶紧广播出去。
3d:每次收到广播来的区块,各节点检验该区块是否符合对区块的要求(至少HASH要好看嘛!),如果符合,就把此块保存下来,然后开始试图出下一个块(也即继续挖矿),把已经收到但尚未打包的交易打包进入下一个要出的块。
4、所有节点都在抢着打包,因为谁能正确打包谁就能得到BTC奖励。
4a:每成功出一个区块,打包者将会被奖励若干个BTC。最早一开始是奖励50个,每210000个区块(大约4年)奖励减半,所以后来是25个、12.5个、现在是6.25个,到2140年就会无币可挖。
4b:事实上,矿工们除了可以得到系统的奖励,还能得到区块中的手续费。
5、每个节点收到区块后,如果验证无误,就接受该区块,将其附加到自己保存的区块链上。
5a:由于每个节点都和其他节点不断同步,所以每个节点(全功能节点)都保存着从第一个区块到现在这个区块的数据(目前已经产生将近70万个区块)。
5b:一个区块的头部,会含有本区块体内全部交易的merkle根(其实也是一种HASH计算啦),如果区块体内的某个交易被篡改,可以通过计算merkle根,和头部的merkle根比较,从而发现篡改。
5c:一个区块的头部,还会含有上个区块头部的HASH值(可以简称为区块的HASH)。这就可以校验上个区块是否完整、正确(因为任何数据差错,都做不出好看的HASH了)。你可以从最新的区块,一直追溯到创世区块(第一个区块),确保没有任何数据被改动过。
5d:整个区块链上,如果其中任何一个区块,有任何一点点的篡改,都会导致这个区块的HASH值不再是一个好看的HASH,也会导致其后区块的HASH都不再好看,任何明眼人,都会知道数据不对了。而每个好看的HASH,都是全球若干矿工,使用若干矿机,花着若干电费,辛辛苦苦挖出来的。一个试图篡改区块的人或组织,没有这么强大的能力。
结语
现在,你是不是了解了HASH,了解了挖矿,了解了区块链为什么这么能防篡改了呢!
我简单总结一下:
HASH很容易计算,但反过来倒推就不容易;输入有一点改变,输出就会大变;对于一个好的HASH算法,不同的输入,肯定会是不同的输出,不用担心碰撞;HASH值可以当作ID来看待;通过对比HASH,可以判断输入是否被人改了。
挖矿是为了给一个区块找一个好看的HASH,也即前面若干位是0的HASH;不管有多少节点在挖矿,都能够自动、简单地调整难度,使得保证大约10分钟才能找到一个好看的HASH;每个区块都将自己那个好看的HASH,放在下一个区块的头部;每个全节点都记录着所有区块的数据,而且可以很方便的验证所有区块没有被人改动过;如果有人想改历史区块里的数据,那要费老鼻子劲了!