区块链技术基础篇之二:白话哈希算法

区块链技术基础篇之二:白话哈希算法

聊到区块链的时候也少不了会听到“哈希”、“哈希函数”、“哈希算法”,是不是听得一头雾水?别急,这一讲我们来讲讲什么是哈希算法。

哈希算法:简单地说,就是给一堆复杂的信息取一个简单的、容易记的、固定长度的别名

帮助理解 : 别名(外号)有可能重名,但是对于具体的一个人只有一个确定的别名(外号)。 所以说,对于一个具体的人可以知道他的外号(比如:小狗子),但是给你一个外号,不一定就能够确定是谁。

哈希算法:为什么要取一个容易记忆的别名

1、为了保密,不让别人知道我的真实内容;

2、更少的记忆存储,不要记那么多东西;

3、大家都变成一样的长度,便于快速排序、查找检索。

什么是哈希算法?

什么是哈希算法?哈希是一种加密算法,也称为散列函数或杂凑函数。

哈希函数是一个公开函数,可以将任意长度的消息M映射成为一个长度较短且长度固定的值H(M),称H(M)

为哈希值、散列值(Hash Value)、杂凑值或者消息摘要。

它是一种单向密码体制,即一个从明文到密文的不可逆映射,只有加密过程,没有解密过程。

一休直白说: 说直白一点哈希算法就是把一堆东西、或者一堆信息、或者数字,进行建索引、建目录,归为固定的几类。因此, 首先你要确定需要分成几类,比如下面十个整数,你是要按照奇数偶数分类,还是按照除3的余数分类,这个分类规则也就是哈希函数。

这样我们就可以计算:

对于函数1:Hash1(311)= 1,hash1(316)= 0;对于函数2:Hash2(311)= 2,hash2(316)= 1

对于前面的十个两位数,现在只要存储一位数就可以了,减少了存储的空间,并且从结果认不出来原来的数字了,达到了加密的效果。

显然,也带来了问题,hash2(311)= hash2(317)= 2,如果我们知道哈希结果为2,是没有办法确定原始数字具体是11还是17,是没法反推的,不可逆。这就是哈希结果的冲突,数学家们就一直在找有没有使得结果不会冲突的算法,当然最后数学家们找到了这种算法,后面会介绍。

即使上面的这样的简单hash含糊在特定场景下也是有用的,比如:对于hash2函数,如果对方告诉了我哈希结果是2,同时我收到了他发给我的原始数字是312,那我可定可以判断这个数值肯定不对,因为hash2 (312)= 0。

哈希算法

“好的”哈希算法或函数会有以下特性:

  • 正向快速: 给定一个原文,可以在一定的时间内快速算出hash值;
  • 逆向困难: 当知道某一个hash值,没办法算出这个hash值所对应的原文;
  • 输入敏感: 只要原文中有稍微的改动,哪怕只是增加了一个标点符号或者一个空格,都会导致得出的结果完全不同;
  • 避免冲突: 不同的输入不能产生相同的输出,简单的说就是很难找到两段不同原文的hash值是一样的。

前面我们介绍的两个哈希函数举例只是为了讲解哈希原理, 显然都不是好的哈希算法或函数,因为不同的数值出来相同结果的冲突概率太大了。

主要的哈希算法

现在来讲讲哈希算法的种类,哈希算法主要有MD5、SHA1、SHA2、SHA256、SHA512、SHA3。

SHA:Secure Hash Algorithm; MD:MessageDigest; RIPEMD(RACE Integrity Primitives Evaluation Message Digest)

MD5是输入不定长度信息,输出固定长度128bits的算法,这个算法在04年就被破解了,而SHA1也在17年被Google攻破。

目前比较常用的是SHA2和SHA3,这两个都支持了更长的摘要信息输出,提高了安全性,SHA2主要有SHA224、SHA256、SHA384和SHA512,数字后缀表示它们生成的哈希结果长度。

比特币区块链使用的就是SHA-256(安全散列算法)和RIPEMD160

在区块链中,通常使用SHA–256(安全散列算法)进行区块加密,这种算法的输出长度为256位,输出的是一串长度为32字节的随机散列数据。 区块链通过哈希算法对一个交易区块中的交易信息进行加密,并把信息压缩成由一串数字和字母组成的散列字符串。区块链的哈希值能够唯一而准确地标识一个区块,区块链中任意节点通过简单的哈希计算都可以获得这个区块的哈希值,计算出的哈希值没有变化也就意味着区块中的信息没有被篡改。

哈希算法主要应用场景,区块链主要涉及前面三种场景

1、场景一:安全加密,保密性

日常用户密码加密通常使用的都是 md5、sha等哈希函数,因为不可逆,而且微小的区别加密之后的结果差距很大,所以安全性更好。

2、场景二:唯一标识 ,快速查找,减少存储空间

比如 URL 字段或者图片字段要求不能重复,这个时候就可以通过对相应字段值做 md5 处理,将数据统一为 32 位长度从数据库索引构建和查询角度效果更好,此外,还可以对文件之类的二进制数据做 md5 处理,作为唯一标识,这样判定重复文件的时候更快捷。

3、场景三:数据校验,快速的身份验证,信息完整性验证

比如从网上下载的很多文件(尤其是P2P站点资源),都会包含一个 MD5 值,用于校验下载数据的完整性,避免数据在中途被劫持篡改。

4、场景五:散列函数

前面已经提到,PHP 中的 md5、sha1、hash 等函数都是基于哈希算法计算散列值

5、场景五:负载均衡

对于同一个客户端上的请求,尤其是已登录用户的请求,需要将其会话请求都路由到同一台机器,以保证数据的一致性,这可以借助哈希算法来实现,通过用户 ID 尾号对总机器数取模(取多少位可以根据机器数定),将结果值作为机器编号。

6、场景六:分布式缓存

分布式缓存和其他机器或数据库的分布式不一样,因为每台机器存放的缓存数据不一致,每当缓存机器扩容时,需要对缓存存放机器进行重新索引(或者部分重新索引),这里应用到的也是哈希算法的思想。

区块链中的哈希算法

在区块链中很多地方都用到了hash函数:

1.区块链中节点的地址、公钥、私钥的计算。以地址为例:公钥经过一次SHA256计算,再进行一次RIPEMD160计算,得到一个公钥哈希(20字节\160比特),添加版本信息,再来两次SHA256运算、取前4比特字节,放到哈希公钥加版本信息后,再经过base58编码,最终得到地址。

2.构建merkle tree:是数据结构中的一种树结构,可以是二叉树,也可以是多叉树,他和数据结构中树的特点几乎一致,和普通树不同的是:merkle tree上的叶节点存放hash计算后的hash值, 非叶节点是其对应的子节点串联的字符串的hash值。用于区块头和SPV认证中。

3.比特币中的挖矿,工作量证明(pow),计算的其实就是一个nonce,当这个随机数和其他散列过的数据合并时,产生一个比规定目标小(target)值。挖矿也可以理解一种快速不可逆的计算。SHA256(SHA256(version + prev_hash + merkle_root + ntime + nbits + x )) < TARGET。

4.比特币中的bloom filter布隆过滤器,布隆过滤器基于hash函数的快速查找。解决了客户端检索的问题,原理是Bloom filter可以快速判断出某检索值一定不存在于某个指定的集合,从而可以过滤掉大量无关数据,减少客户端不必要的下载量。

区块链中的哈希算法场景1:区块链中节点的比特币钱包地址、公钥、私钥的加密

从比特币私钥得到我们日常转账所用的比特币钱包地址总共需要九个步骤,中间用到了SHA256加密、RIPEMD160加密和BASE58编码。

公钥经过一次SHA256计算,再进行一次RIPEMD160计算,得到一个公钥哈希(20字节\160比特),添加版本信息,再来两次SHA256运算、取前4比特字节,放到哈希公钥加版本信息后,再经过base58编码,最终得到地址。

RIPEMD(RACE Integrity Primitives Evaluation Message Digest),即RACE原始完整性校验消息摘要。RIPEMD使用MD4的设计原理,并针对MD4的算法缺陷进行改进,1996年首次发布RIPEMD-128版本,它在性能上与SHA-1相类似。

RIPEMD-160是对RIPEMD-128的改进,并且是RIPEMD中最常见的版本。RIPEMD-160输出160位的Hash值,对160位Hash函数的暴力碰撞搜索攻击需要280次计算,其计算强度大大提高。RIPEMD-160的设计充分吸取了MD4、MD5、RIPEMD-128的一些性能,使其具有更好的抗强碰撞能力。它旨在替代128位Hash函数MD4、MD5和RIPEMD。

区块链中的哈希算法场景2:消息的完整性进行验证

哈希算法主要是用于对信息内容的的完整性进行验证,保证这个内容是原始的、没有被修改的。

举个例子,现在有原文A,对它进行哈希运算得到一个hash值,要验证这个原文是否有被篡改过只需要把内容文件使用相同的哈希算法进行哈希运算,将得出的hash值与原来的hash值进行对比,如果一样则可以判定该内容没有被修改过,这其实是使用到了哈希算法的输入敏感这一特性。

现在很多区块链项目对于存储数据也是采用这种思路,基本都是hash上链,就是将内容文件进行hash运算得到hash值,将这个hash值存到区块链中,而将原文存到某一台中心服务器,当要使用原文时就到链上取到对应的hash值,然后使用相同的哈希算法计算出hash值,接着对比这两个hash值来判断原文件是否被修改过,通过这种做法间接保证了原文数据的不可篡改性。

至于为什么不直接原文上链,因为原文的数据比较大,如何有效存储庞大的数据是当前区块链面临的问题。

区块链中的哈希算法场景3:数字签名

在区块链中的非对称加密也使用到了哈希算法。

非对称加密的过程: A想要发送消息给B,A首先会对消息原文进行数字摘要(哈希算法也称为摘要算法),然后使用自己的私钥对摘要进行签名(就是加密)得到数字签名,然后使用B的公钥对原文进行加密(B的公钥是公开的),接着将密文以及数字签名发送给B,B拿到这两个信息之后使用A的公钥(A的公钥也是公开的)对数字签名进行解密得到一个hash值,暂时称为Hash1,然后使用自己的私钥对密文进行解密得到原文(这一步保证的是原文是发给B的,而不是发给C或者D,因为只有B的私钥才可以解开密文),拿到原文之后B就还是使用相同的哈希算法对这个原文进行哈希运算得到Hash2,将Hash1与Hash2进行对比,如果完全一致则说明消息在传输的过程中没有被篡改过。这就解决了两个问题,一个是明确消息发给谁,而是消息在传输过程中没有被篡改。

区块链中的哈希算法场景4:比特币中的挖矿,工作量证明PoW

比特币中的挖矿,工作量证明(pow),计算的其实就是一个nonce,当这个随机数和其他散列过的数据合并时,产生一个比规定目标小(target)值。挖矿也可以理解一种快速不可逆的计算。

不断的尝试nonce,新换一个 nonce,重新计算两次SHA256,看看结果是否小于TARGET,谁最先找到这样一个nonce,谁就在本次挖矿比赛中胜出,就能够得到比特币奖励。

目标值=最大目标值 / 难度值

其中,最大目标值为一个恒定值:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

目标值的大小与难度值成反比。比特币工作量证明的达成就是矿工计算出来的区块哈希值必须小于目标值。

我们也可以简单理解成,比特币工作量证明的过程,就是通过不停地变换区块头(即尝试不同的随机值)作为输入进行SHA256哈希运算,找出一个特定格式哈希值的过程(即要求有一定数量的前导0)。而要求的前导0的个数越多,代表难度越大。




编辑: Victorlamp -e休

发布于 2023-04-29 08:39 ・IP 属地广东

文章被以下专栏收录