弄明白HASH,你就弄明白区块链的一大半

“人类历史上第一次,全世界各地的人,花费巨额的成本,争前恐后地寻找美学意义上的数学运算结果。”

—卫sir

Beeple加密艺术作品《区块链》

说起区块链,似乎大家都懂一点,再往细里一问,似乎又都不懂了。

比如,你问一个人:为什么要挖矿,挖的到底是啥。

怕是没几个明白人。

本文就是要给你讲明白!

前言

人们一说起区块链,就常常说防篡改防篡改,那么,这个防篡改是怎么做到的呢。

主要靠HASH。

人们所常说的挖矿,其实是在挖HASH。

挖一个长得很好看的HASH。

但,什么是HASH?

外行人是说不清的,内行人,似乎也很少能给外行人讲明白。

很多人喜欢用比喻的方式给外行人讲HASH,其实,你就是弄100个比喻(什么麻将、扑克、骰子啥的),不懂HASH的人还不懂。

他们中比较傻白甜的,甚至会想,挖矿是在挖麻将吗?

真正想弄明白HASH,就让他看看HASH长什么样子呗!!

HASH到底是个啥

HASH是一个算法,你给它一串数,它给你一串数。

你给它的叫输入,它给你的叫输出。

也就是说,将数据输入给HASH函数,HASH函数输出一串数。

HASH( 输入 )= 输出

这就好比你把一头猪输入给一个香肠机,香肠机给你输出一段香肠。

看个例子吧,我们以最常见的HASH算法MD5为例。(当然,有很多种HASH算法,MD5是其中最知名的一个。)

MD5 ("weijianfan") = c49262b1117b9fd1d6ebd74aaa016f3e

上面这个例子中,“weijianfan”是输入,后面那串数是输出。

再如:

MD5 ("weiyuerenhua") = a799c7c504a1a80f95ebe69a86c42637

注意,HASH函数有个重要的特点,不管输入多长,输出都是固定长度的。

当然,和一般的算法一样,只要输入不变,输出是不变的。

比如MD5,输入是不限制长度的,输出就是128位的二进制,也就是16个字节的十六进制。像上面第一个例子里,c4就是一个字节,代表了8位的二进制,即11000100,最后那个3e也是一个字节,也即00111110

我们把输入搞长点:

MD5 ("In Math We Trust.") = 767fa54f12bab6b71fb411f265814bb7

把汉字作为输入:

MD5 ("博鳌亚洲论坛2021年年会数字支付与数字货币分论坛4月18日晚举行。") = 36b5e89c797d22d14ccefe4ec79f56c2

再搞长点:

MD5 ("Andreas M. Antonopoulos is a noted technologist and serial entrepreneur who has become one of the most well-known and well-respected figures in bitcoin. An engaging public speaker, teacher, and writer, Andreas makes complex subjects accessible and easy to understand. Andreas advises multiple technology startups and speaks regularly at conferences and community events around the world.") = 5ac503b01e213d4794d92134096ad313

长一点的汉字:

MD5 ( "Andreas M. Antonopoulos 是⼀位著名的技术学家和连续创业企业家,⽐特币界最著名和倍受尊敬的⼈物之⼀。⾝为⼀名迷 ⼈的公共演说家、教师和作家,他善于把复杂的问题变得简单⽽易于理解。作为⼀名顾问,他则帮助初创者认知、评估并指 引减⼩安全和业务风险。") = 90f039293e0b3da5516e251b93434795

HASH还有一个特点,只要输入有一点点的变化,输出都会完全不同,就好像输入是完全不同的。

比如把上面这段文字中“一位”里的“一”字删掉,再做HASH:

MD5 ("Andreas M. Antonopoulos 是位著名的技术学家和连续创业企业家,⽐特币界最著名和倍受尊敬的⼈物之⼀。⾝为⼀名迷 ⼈的公共演说家、教师和作家,他善于把复杂的问题变得简单⽽易于理解。作为⼀名顾问,他则帮助初创者认知、评估并指 引减⼩安全和业务⻛险。") = 159c9d192e45fbd2eaa0c3f068a78508

看到了吧,输入有微小的变化,输出会完全不同。

HSAH对输入是不挑的,不管是字符串,还是文件,不管是文本、图像、视频,只要是数字的,都当作二进制输入就是了。

比如,把下面这幅图像给MD5,可以得到:

MD5 (Emily Blunt.jpg) = b818d284ef28f733c701f7bc1ee5f669

图|艾米莉布朗特,英国最受欢迎的女演员

如果你的电脑上有md5工具,你就可以试试自己做HASH,比如在mac电脑里,在“终端”中输入md5 -s "xxx",或者md5 1.txt就可以对字符串或者文件进行md5。

若干G的视频文件也没问题:

MD5 (伟大的转折-01.mp4) = 9093c85d13f79609978f52c48e19aa65

图|38集革命历史剧《伟大的转折》,遵义会议会址

你哪怕是改动了这个视频中任何一帧的任何一个像素,MD5算出来的结果都截然不同。

所以,判断一个文件是不是被人改动过,算一下HASH就行,HASH只要没变,文件就没有被动过。(前提是这个HASH算法还不错!)

现在你对HASH大概有点印象了吧,反正只要是数字的输入,都能给你整出一段固定长度的输出,而且个个都不一样。

啥是好看的HASH

答:好看的HASH就是前面有很多位0的HASH。—卫sir

HASH输出是比较均匀分布的,基本上,你对任意16个不同的输入做HASH,第1位是0的概率是1/2(大概有8个),前两位是0的概率是1/4,前3位是0的概率是1/8,前4位都是0的概率为1/16。

我们做个实验看看对不对,以下的输入都是随意给的:

1、MD5 ("ionnoouyd") = c78a3b60314d11fc9e739aef407989f5
2、MD5 ("njjiuhbh") = 9aee0690f6002392b2c6fc0d2224adb2
3、MD5 ("88990933") = b19bf0928fc649d99b1cdf02748ae88e
4、MD5 ("-sr&&fvbgt") = 24cc429a2636ac1b9092cf3f681bba09
5、MD5 ("区块链技术") = 649e6048a32c09299e1c952347ccac7e
6、MD5 ("hashcash is very good") = 8015b497b3a9bd6ca7ba1213a731b1a1
7、MD5 ("CC0-MIT") = cd08de7f0f219d8e13437c65974f9773
8、MD5 ("beihaimuchang") = 7cd9a24efce05bbceb01c9020d904294
9、MD5 ("wqqwrr2") = 1cb1797fb57add01523fbd6e86ca2b73
10、MD5 ("1123ed") = ae49266f10e08922780afeb664fd61dc
11、MD5 ("hello world") = 5eb63bbbe01eeed093cb22bb8f5acdc3
12、MD5 ("niahoa...") = 5d3e60365ff999e68a932da4619a129b
13、MD5 ("blockchain") = 5510a843bc1b7acb9507a5f71de51b98
14、MD5 ("随机发均出版后我给") = 18eb95457ec90f1c33fa5914579730d7
15、MD5 ("93002712") = 0abf0bd1dbb35366c56b26d157686f0f
16、MD5 ("13811031123") = 940ca3847eec1e99e716975bc7096c8d

前面说过,MD5输出是128位的,上面是用16进制展示的,比如第一个输出的第1字节是“c7”,第二个输出的第1字节是“9a”,用2进制表示就是“11000111”、“10011010”。依此方法,上面16个HASH输出也就是(省略号代表省略了后面的位):

HASH01  c7………:11000111……………………
HASH02  9a………:10011010……………………
HASH03  b1………:10110001……………………
HASH04  24………:00100100……………………
HASH05  64………:01100100……………………
HASH06  80………:10000000……………………
HASH07  cd………:11001101……………………
HASH08  7c………:01111100……………………
HASH09  1c………:00011100……………………
HASH10  ae………:10101110……………………
HASH11  5e………:01011110……………………
HASH12  5d………:01011101……………………
HASH13  55………:01010101……………………
HASH14  18………:00011000……………………
HASH15  0a………:00001010……………………
HASH16  94………:10010100……………………

你们可以数数,前1位、前2位、前3位、前4位是0的HASH个数,是不是和上面说的概率差不多?

当然,我最喜欢的是那个前4位都是0的,HASH15,它在这16位里面是长得最好看的。

它出现的概率大概就是每16个HASH里面出一个。也就是2^4次出一个。

那么,多少次才会出来一个前20位都是0的HASH呢。

2^20次。

2^20就是2的20次方,就是1,048,576这么多啦!一百万还多啦!所以想在你的电脑上找到它,得算一会呢~

前20位是0,就是16进制前5个数为0,大概就是下面这个样子

00000fc7f1d91e9053995f707a90971d

是不是很好看?

至少比前面出现过的都好看。

当然还不是最最好看的,全宇宙举世无双好看的那个HASH,是全0。

这个全0的HASH,应该还从来没有被算出来过,不知道人类灭亡前能否靠运气找出来。

总之,我说的好看,就是前面有很多个0。

0越多,越好看。

好的HASH算法有什么特点?

注意HASH算法有很多,比如MD5、SHA-1、SHA-2等,再如BTC用的SHA-256和RIPEMD-160等。

至少有这么两个特点:

1、对于任意两个不同的输入,应该产生不同的输出。(这叫抗碰撞)

2、正向计算很容易,反过来从输出倒推输入,就非常难,只能靠暴力猜。(这叫不可逆)

先看第一个特点:抗碰撞

一个好的HASH算法,对于任意两个不同的输入,应该产生不同的输出。

事实证明,MD5、SHA-1不能算很好的HASH算法,因为王小云院士等人,已经可以找到两个不同的输入,产生相同的HASH输出。具体可以看看相关文章12

如何形象理解这个特点呢?

首先,这个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,放在下一个区块的头部;每个全节点都记录着所有区块的数据,而且可以很方便的验证所有区块没有被人改动过;如果有人想改历史区块里的数据,那要费老鼻子劲了!

不过这只是一大半,还有一些东西你是不了解的,也不是本文所想描述的。

你如果对其他的东西感兴趣,请留言。

文|卫剑钒


  1. https://www.zhihu.com/question/19743262/answer/289095984 

  2. https://www.zhihu.com/question/56234281/answer/148349930

猜你喜欢

转载自blog.csdn.net/vigor2323/article/details/117888051