定义哈希函数H,将可变大小的数据Data作为输入,产生固定长度的h值。# h, F: v0 T L2 \9 e% {
密码学哈希函数,是一个数学函数。哈希函数本身拥有的特征:
1、输入任意性:函数的输入可以是任意大小的数据;$ v- b3 w8 N9 z7 b* v
2、输出固定性:函数的输出是一个固定大小的数据;& ?; }2 M0 ]) W$ \
3、能够进行有效计算:也就是说在一个合理的时间内,能够对输入数据进行运算得出输出。
对于区块链技术以及加密数字货币而言,要使得哈希函数达到密码安全,还需要要求其具有以下特性:* q: W0 x4 e5 V7 d
1、碰撞阻力碰撞的概念:如果有两个不同的值X,Y,H(X)=H(Y)成立,则称哈希函数H产生了碰撞。而碰撞阻力是指无法找到两个不同的值X,Y使得H(X)=H(Y)。5 b, W( J- S( B3 f! R& ?. E
由碰撞阻力的解释和哈希函数的特性,会很容易的得出产生碰撞是一个必然的现象。因为哈希函数的输入空间是任意大小的数据,而输出是固定大小的数据。这就意味着输入空间比输出空间大,因此碰撞是必然的。
例如,如果我们定义哈希函数的输出只有0和1两种结果,那么很显然碰撞是很容易发生的。
那么一个优良的哈希函数,应该是这样的:" v2 O! v& B6 e8 @# ~( C0 a" P
任意y,找x,使得H(x) = y,非常困难给定x1, 找x2, 使得H(x1) == H(x2), 非常困难找任意的x1, x2, 使得H(x1) == H(x2), 非常困难例如,对于一个256位输出的哈希函数而言,最坏的情况是要进行2256+1次哈希运算,平均也要2128次哈希运算。这个量级,差不多是一台PC机算10^27年的时间。所以,我们可以认为这件事是具有碰撞阻力的。( u( W+ B# |% o
正是因为有了碰撞阻力,所以才有了哈希上链的说法。所谓哈希上链是典型的存证场景:这个场景可以让我们将哈希输出作为信息摘要写进区块链的区块结构中。例如有某一份非常重要的文件,文件非常大,将文件本身写入区块链中并不可行,所有者A又希望该文件在后续的使用中安全可靠,不会有被篡改的风险。于是所有者A将该文件做一次哈希,并将哈希值写入区块链中。后续在使用的过程中,只需要对要使用的文件做一次哈希,并与在区块链中的哈希值进行对比即可。如果哈希值相同,则证明没有被篡改,如果哈希值不同,则证明被篡改过。8 X: Q! {/ x! y* d( f( u+ M3 O
2、单向性(隐秘性)单向性(隐秘性)是指,如果我们只知道哈希函数的输出h=H(X),没有可行的算法算出输入值X。5 t0 e( U. b" i7 P/ G: R
常见的哈希算法有:MD5,SHA1,SHA224,SHA256,SHA384,SHA512,SM36 v4 [5 M9 N8 b% A
SHA-256是一个主要被比特币世界采用的比较有效的哈希函数。
哈希指针以及数据结构:哈希指针是一种数据结构,是一个指向数据存储位置以及位置数据的哈希值指针。我们在学习C语言的时候知道一个普通的指针就是一个地址,能够指向数据存储的位置。但是哈希指针不但能够告诉你数据存储的位置,还能够告诉你这个位置的数据是否被篡改过。也就是可以明确某个时间戳下该数据的哈希值的指针。
通过哈希指针构建的链表,实际上就是区块链。6 V) ?1 w! V2 ~; _. V5 J5 M; M( B0 L
如下图所示:
普通链表结构:
普通链表结构
区块链结构:3 V, G" d3 N( s& B9 m
. Q6 c$ m( H0 X1 c) D
区块链表结构
因此,区块链的一个典型应用就是“防篡改”。9 B- x1 O; O3 v4 S9 H9 y
梅克尔树(Merkle trees):使用哈希指针的二叉树,就是梅克尔树。在梅克尔树的结构中,所有的数据块都被两两分组,每两个数据块的哈希指针被存入这两个数据块的父节点中,两个父节点的哈希指针又被存入到他们的父节点中,以此类推,一直达到梅克树的根节点。
其结构如图所示:& U% Y! f$ L( T/ B5 G
1 u0 q4 T4 v; {- m, I
梅克尔树- `) v* E Q" Z. @. J# J8 H
梅克尔树的特点——隶属证明9 ?8 l7 A+ Q6 {
假设,需要证明某一个数据区块隶属于某一个梅克尔树,则只需要展示数据区块的信息,以及数据区块通向树根节点的区块信息即可验证。可以忽略树的其他部分。; `: `. Z" O% L
如下图所示:如果我们要验证D3是否属于ROOT树,则只需要展示D3,N2,N5这几个节点的信息。
: W& \, X5 {) a
隶属关系
成为第一个吐槽的人