哈希函数简介

哈希函数入门介绍。

一点说明
本文中英文和二进制之间的相互转换并没有遵循任何模式,请读者不要纠结于这一点。当然,实际中,有很多方法用于将我们熟知的字符(例如中文、英语等)转换为二进制(十六进制),如果感兴趣,可以点击下面的参考中的内容

哈希函数,又称散列函数,广泛应用于互联网的各处,包括但不限于安全地存储密码、查找重复记录、快速存储和检索数据等。例如,Qvault 应用使用哈希将主密码扩展为私人加密密钥。你还可以 点击这里 查看哈希函数用于何处。

哈希函数的拥有如下三个重要特性,这些特性可以说是最重要的特性:

  • 哈希函数对数据进行确定性加扰。

  • 无论输入是什么,哈希函数的输出始终具有相同的长度(大小)。

  • 无法从加扰数据中检索原始数据(单向函数)。

想象一下,如果随机扭动一个魔方,到最后会得到一些和开始时不一样的东西。但是,如果重新开始,并做完全相同的一系列动作,那么将能够反复得到完全相同的结果。尽管结果可能看起来是随机的,但它其实是严格按照一定的规则进行变幻地,这就是确定性加扰的含义。

确定性对于安全存储密码很重要。例如,假设我的密码是 iLoveBitcoin,我可以使用哈希函数对其进行加扰:

iLoveBitcoin → “2f5sfsdfs5s1fsfsdf98ss4f84sfs6d5fs2d1fdf15”

现在,任何人看到加扰后的版本,他们都不会知道我的原始密码!这一点很重要,因为这意味着作为一个网站开发人员,我只需要存储我用户密码的哈希(加扰数据)就可以验证它们。当用户注册时,我将用户密码进行哈希运算然后将其存储在我的数据库中。当用户登录时,我只是对他们输入的内容再次进行哈希运算,并比较两个哈希值。因为给定的输入总是生成相同的哈希值,所以能够很方便地进行验证。

如果对单个单词进行哈希处理,则输出将具有一定的大小(对于 SHA-256,则为特定的哈希函数,大小为 256 位)。即便我对一本书进行哈希处理,输出同样将是相同的大小。

这是另一个重要的功能,因为它可以节省我们的计算时间。 一个典型的例子是使用哈希作为数据映射中的键。 数据映射是计算机科学中用来存储数据的一种简单结构。

https://fastly.jsdelivr.net/gh/techkoala/techkoala.github.io@master/images/Algorithm/Hash/key-map.webp
数据映射

当程序在映射中存储数据时,会为映射指定一个键和值。当程序想要访问该值时,它只要提供适当的键就能接收相应的值。数据映射很好,因为它们可以立即找到数据。计算机通过键可以立即找到对应的值,而不是花费数小时在数百万条记录中搜索。

因为键类似于地址,所以它们不能太大。如果我想将图书存储在数据映射中,我可以对图书的内容进行哈希,并使用该哈希作为键。

接下来,以 LANEHASH 算法为例,简要讲解哈希处理是如何完成的。

  1. 首先,选取下面的数据进行哈希处理

    iLoveBitcoin

  2. 将字母转换成二进制

    iLoveBitcoin→ 100010100000101111

    注意
    在这一步中,我们通过各种预定的步骤来转换我们的原始数据。转换方式可以采用各种方式,但重要的是,每当我们使用 LANEHASH 时,都需要使用相同的步骤,以便我们的算法是确定性的。
  3. 将比特前四位从左移到右边

    100010100000101111 → 101000001011111000

  4. 奇偶分离比特

    101000001011111000 → 110011110 & 000001100

  5. 分别转化为十进制数

    110011110 → 414

    000001100→ 12

  6. 两数相乘

    414 *12 = 4968

  7. 乘积平方

    4968 ^ 2 = 24681024

  8. 再次转换为二进制

    24681024 →1011110001001101001000000

  9. 剥离右边的 9 个比特以得到 16 位比特

    1011110001001101001000000 → 1011110001001101

  10. 转换回字母/数字

    1011110001001101 → “8sj209dsns02k2”

正如你所看到的,如果在开始时使用相同的单词,则在结束时将始终得到相同的输出。然而,即使你改了一个字母,结果也会发生很大的变化。

哈希函数实际上就是按照特定的规则将数据进行一系列转换,最后得到一串键值用来代替/指代原始数据,但是需要注意的是,哈希函数需要满足确定性、定长性、不可逆性。