哈希函数可谓区块链技术的基础支柱之一,一手支撑著为人们传颂的区块链的不可改变特性。

今天,我们来看一些加密货币中很常见的哈希函数。

首先,了解下什么是哈希。

简言之,将任意长度的输入做哈希计算,可得出固定长度的输出。比特币中,哈希计算的输入是交易。

下面,用SHA-256举例子,看看哈希过程什么样。

输入:Hi

输出:3639efcd08abb273b1619e82e78c29a7df02c1051b1820e99fc395dcaa3326b8

输入:Welcome to NervosFans community.

输出:8f27c00287375a7e3a2129ad42c041c66f5c9c4911872d36a9dbb66ac3324fae

有没有发现,两组输入尽管长度不等,SHA-256计算后,得出的哈希值长度都是固定256位。

那么,处理海量数据及交易时,这就厉害了,相当于把海量数据压缩成了一个个哈希值。

接下来,再看看哈希函数的诸多属性以及在区块链上的实施。

加密哈希函数

加密哈希函数就是适用于加密的哈希函数,称职的加密函数需有如下属性:

属性1:确定性

哈希相同输入,结果总相同。比方说相同的输入每次算出的哈希值都不同,账本里怕是要乱作一团。

属性2:快速计算

函数需要快速返回输入的哈希值。 要知道,计算速度与系统的效率正相关。

属性3:抗原像性或单向性

抗原像性状态指:给定H(A),确定A不可行; A代表输入、H(A)代表输出哈希值。

这里用的是「不可行」,不是「不可能」。解释一下:

比方说掷一个骰子,对朝上数字做哈希。已知:

sha256 (A)=ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d

求A。

答:有鉴于哈希函数的确定性,相同输入的哈希值总是相同的。那么,可以先算出1-6的哈希值,然后挨个比对。

sha256(5)= ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d

A=5。

但是,这个方法只有在数据量很小的情形下有用。数据量巨大的时候,比方说是个128位哈希,就该「强力法」登场了。强力法基本上就是【随机选取输入、哈希、比对】的循环,直到碰对为止。

强力法好玩的地方在于:人品爆发第一次就碰对的可能性有,但是无限趋近于0,但不等于0;人品太次的话,需要碰到最后,也就是2^{128}-1 次,才能碰对。当然,这是两个比较极端的情况。

正常的话:碰到一半碰对, 2^{128} /2= 2^{127}次 ,就是说很长时间的意思。

这里想说的是,强力法是有可能击溃抗原像性的,但是个鸡肋方法,需要很长时间。

属性4:雪崩效应

哈希函数能放大输入的细微变化。举个SHA-256的例子:

两个输入仅句首单词首字母大小写不同,哈希就非常不同了。这就是雪崩效应。

属性5:防碰撞

给定两个不同输入A、B,各自哈希 H(A)、H(B),H(A) = H(B)不可行。

意思是说通常每个输入的哈希都是独特的。解释下什么叫「通常」:

先看个概念,叫「生日悖论」。

说街上随便找个路人,路人恰好跟自己生日同一天的几率很低,是1/365(0.27%)

假设一个房间里有20-30个人,那么其中两人生日相同的几率是50%。

这里涉及概率问题:

假设某事件有N种不同可能性,需N的平方根个随机项才能发生50%碰撞。

回到生日的例子中:生日有365种可能性,365的平方根约等于20。

假设128位哈希,可能性就是2^{128}。根据生日悖论,有一半机会碰撞成功所需次数是2128的平方根,就是2^{64}次的时候。

没有哈希函数是完全抗碰撞的,只是碰撞时间真的很长。

那么SHA-256这种,基本上可以这么理解,若H(A) = H(B),则A=B。

想构造抗碰撞哈希函数的,请参看Merkle-Damgard范式。

属性6:谜题友好

这个属性对于加密货币的影响非常深远。先定义一下:

已知输出Y,若k来自高熵分布,则H(k|x) = Y中求得输入x不可行。

高熵分布

意思是,分布程度高,选这个动作本身近似随机。好比从1-5中选个数字,叫低熵分布;但是,从1到1万亿中选个数,就是高熵分布了。

k|x

|代表串联,意思是把两串字元连起来。好比将blue和sky串联起来,结果得到bluesky。

那么回看下前面的定义,意思是输出值Y已知、k值来自高熵分布,则找出合适的X值,使kx串联的哈希等于Y,不可行。

加密哈希函数的例子:

? MD 5:生成128位哈希,碰撞发生在2^{21}次哈希后。.

? SHA 1:生成160位哈希,碰撞发生在2^{61}次哈希后。

? SHA 256:生成256位哈希。

? Keccak-256:生成256位哈希,以太坊加密演算法。

? RIPEMD-160:生成160位输出,比特币脚本使用SHA 256 + RIPEMD-160。

? CryptoNight: Monero的加密演算法

下面是常见的加密演算法:

安全哈希演算法 (SHA)

安全哈希演算法是个家族,包含:SHA-0、SHA-1、SHA-2和SHA-3。

SHA-2包含长度不等的两种函数:SHA-256 、 SHA-512。

SHA-3,之前叫keccak,也支持256、512两种长度。内部构造与其他SHA迥异。

Image Credit: Wikipedia

仔细看下SHA-256 、顺便看下SHA-3:

SHA-256

SHA-256 用的是32位元字(SHA-512用64位元字)。比特币主要在两个地方著重使用SHA-256:挖矿、生成地址。

挖矿(区块)过程要求矿工首先解决复杂计算谜题后,方可将块添加至比特币区块链中。此过程叫做工作量证明(Proof of Work),涉及SHA-256哈希函数计算。

生成地址过程对就是对公钥哈希,以此进一步保护用户对资产的所有权,且地址长度小于比特币公钥,便于存储。

SHA-3

SHA-3使用海绵函数。

Image Credit: Wikipedia

海绵函数是一类内部状态有限的演算法,输入位任意长度,输出位预定长度。

顾名思义,海绵函数中,数据先被「吸收」进海绵,然后再「挤压」出结果。

分别看下这两个阶段。

吸收阶段:

该阶段,消息被分成各个块并异或成状态的子集,随后使用置换函数f将子集作为整体进行变换。

挤压阶段:

「从相同状态子集读取输出块,使用状态迁移函数f进行交替。被读取及编写的状态部分的大小称为 转换率(用r表示);未被输入/输出触发的部分的大小称为 容量(用c表示)。 容量决定方案的安全性,容量一半时达到最高安全级别。」

然后,考虑以下元素:

? 输入串N

? 填充函数pad

? 置换函数f 运行宽度b的位块

? 转换率r

? 输出长度 = d

? 容量c = b-r

? 海绵函数构造:海绵[f,pad,r](N,d) 得出长度为d的位串Z

能说的再具体点么?

? 首先,用填充函数填充输入串,产生位串P,P的长度可被r整除。

? P/r,得P[0] 到 P[n-1]的n个连续r位块。

? 然后将状态S初始化为一串0位的b。

? 填充了P的每个块开始被吸收:

a) 使用0位c填充每个块p[i],直到p[i]长度为b。

b) 用S异或长度为b的p[i],S表示上一个块的状态。

c) 最后使用置换函数f,产生新状态。

注:每个块都产生一个新状态S。

? 初始化结果Z为空串。

? 若Z长度小于 d:

a) 将S的首个r位添加至Z。

b) 若Z长度依然不够,使用置换函数f产生新状态,然后将位添加至Z。

? 若Z长度大于d,则舍位至d位。

SHA-3 长这样:

输入: Hi

输出:

154013cb8140c753f0ac358da6110fe237481b26c75c3ddc1b59eaf9dd7b46a0a3aeb2cef164b3c82d65b38a4e26ea9930b7b2cb3c01da4ba331c95e62ccb9c3

RIPEMD-160 哈希函数

RIPEMD由一组比利时研究人员开发, 1996年首次公布。

RIPEMD基于MD4的设计原则,但性能与SHA-1十分类似。 RIPEMD-160是RIPEMD的160位版本,常用于生成比特币地址。

比特币公钥首先过一道SHA-256,然后再过一道RIPEMD-160,就生成地址了。 多出来的一道程序是因为160位比256位小不少,主要起节省空间的作用。

另外,RIPEMD-160唯一能生成最短哈希且独特性有保障的函数。

Image Credit: Wikipedia

上图是RIPEMD-160演算法的压缩函数下的子块。

RIPEMD-160 长这样

输入: Hi

输出: 242485ab6bfd3502bcb3442ea2e211687b8e4d89

The Ins and Outs of Cryptographic Hash Functions (Blockgeeks Guide)?

blockgeeks.com
图标

推荐阅读:
查看原文 >>
相关文章