区块链前置知识之Hash (一)

区块链
我们定义这样一个场景,约定任意正整数,要存放在长度为 6 的数组中,那么此时,我们可以利用 hash 的思想设计什么样的方案来做到这个事情呢?

定义

hash 是一种把任意长度输入变换成固定长度输出的一种算法。

假设我们已经定义了一个 hash 函数名为 H,输入内容为 message,输出内容为 x,那么就有如下公式。

H(message) = x

这是一个压缩的过程,通常情况下,我们会把输出值称之为 hash 值。

接下来通过一个具体的案例来了解 hash 的过程。

我们定义这样一个场景,约定任意正整数,要存放在长度为 6 的数组中,那么此时,我们可以利用 hash 的思想设计什么样的方案来做到这个事情呢?

数组的具体位置我们可以用下标来表示 0, 1, 2, 3, 4, 5。想要将任意正整数放入到数组中,那么我们只需要设计一个函数,输入值为任意正整数,输出值为该数组下标中的任意一个即可,得到了输出值,我们就相当于知道应该把输入值放到数组中的某个位置了。

图片

我们可以使用求余法来定义这个 hash 函数。

function suplus(number) {
return number % 6
}

于是,随便取几个数,得到 hash 值之后就能存入数组对应的位置。

// 输入值:61
suplus(61) = 1

图片

// 输入值:101
suplus(101) = 5

图片

此时的哈希值表示的是数组的下标,因此在很多应用场景,输出结果哈希值也被称为哈希地址。

哈希碰撞

在上面的例子中,输入值的范围一定大于输出值的范围,这是 hash 的重要特性之一。因此在某些情况下,不同的输入会得到相同的输出结果。

// 不同的输入,得到了相同的输出,哈希地址相同
suplus(7) = 1
suplus(61) = 1

此时哈希地址相同,按照规则,我们不得不把不同的值,存入相同的位置,这种情况就被称之为哈希碰撞(collision)。

解决哈希碰撞的方法很多,这里介绍一个比较常见的方法:以数组的每个地址为根节点,构建一个新的链表。

例如当输入数字分别为 7, 61 时。

图片

但是当数据量庞大时,链表的查询速度比较低效,因此我们在实践中,会将链表替换成红黑树等操作效率更高的数据结构。

当然,最理想的情况是输出范围足够广,不出现 hash 碰撞。因此我们实践中使用的 hash 函数,输出值的范围都非常庞大,例如早期用得比较多的 md5,现在使用比较多的sha256:比特币中使用的哈希算法。但是由于输入值范围一定大输出值范围,因此理论上哈希碰撞一定会存在。

现在 md5 已经可以人为制造 hash 碰撞,因此实用性大大降低。

本文转载自微信公众号「这波能反杀」,可以通过以下二维码关注。转载本文请联系这波能反杀公众号。

责任编辑:姜华 来源: 这波能反杀
相关推荐

2021-04-09 06:25:41

区块链区块链技术

2018-10-23 10:55:07

2020-02-10 11:32:11

区块链blockchain智能合约

2019-11-22 11:10:26

区块链技术

2021-02-02 10:40:10

区块链版权保护技术

2022-08-08 11:53:02

区块链CIO

2019-06-24 16:30:33

区块链零知识证明比特币

2019-12-10 10:49:40

区块链币天销毁比特币

2018-06-25 10:25:26

区块链跨链协议

2021-05-19 10:37:16

WebFlux 前置工具

2022-10-26 08:42:28

2018-03-07 14:06:23

区块链数字货币比特币

2018-06-14 11:02:37

区块链支付宝去中心化

2018-03-30 10:10:11

区块链数字货币记账模式

2021-04-18 06:58:35

区块链账本结构

2018-11-13 14:41:35

溯源区块链商场

2018-08-06 15:41:49

2021-06-01 10:41:11

WebFlux 数据Backpressur

2023-05-30 00:07:33

区块链数据结构

2021-07-29 16:58:22

区块链比特币数字货币
点赞
收藏

51CTO技术栈公众号