Skip to content

哈希函数

哈希函数是一种把任意长度数据 → 固定长度输出 的算法

特点

固定长度输出

无论输入多长,输出长度固定。

例如:

  • SHA256 → 256 位(32 字节)
  • MD5 → 128 位(16 字节)

不可逆

无法从哈希值反推出原始数据。

js
A → hash
但不能 hash → A

雪崩效应

输入哪怕改一个字符,结果都会完全不同。

js
hello
→ 2cf24d...

hellO
→ 872e4e...

一致性

相同的输入,相同的算法,必定具有相同的输出

常见哈希算法

算法长度(HEX)是否安全说明
MD532❌ 不安全已被破解
SHA25664✅ 安全常用
SHA512128✅ 安全更强

哈希是不安全的

虽然哈希值不可逆,但是哈希具有一致性,因此通过暴力枚举,就有可能得到原始值。

因为哈希输出是固定长度,而输入是无限可能。当输入数量超过输出空间,就一定会出现碰撞(哈希碰撞)。(例如 SHA256 只有 2²⁵⁶ 种结果)。

哈希碰撞在数学上必然存在,但在工程上可以忽略。

应用

密码存储

数据库通常不会存储明文密码,会将原始密码转为哈希值存入数据库。

js
password → hash → 存数据库

验证时

js
输入密码 → hash → 对比数据库

文件完整性校验

下载文件后:

js
文件 → 计算 hash
对比官方 hash

一致 说明文件未被篡改

bcrypt

bcrypt 是一种专门用于密码存储的慢哈希算法。bcrypt 设计目标不是“快速算出哈希”,而是“让破解变得非常慢”。

bcrypt通常需要第三方库支持

原理

bcrypt 哈希值的特点是加密后的字符串包含了加密时的算法版本、成本因子、盐、和最终得到的哈希值

js
$2a$10$7mG.bF32bv36IBLetWB11O6zMAXe9Zc5P7cTkfgqTol7yVspl37Va
js
$算法版本$成本因子$盐值+哈希结果
  • 算法版本

表示 bcrypt 版本。

  • 成本因子

成本因子来控制计算轮数。

js
cost = 102^101024 次运算
cost = 122^124096 次运算

bcrypt 会自动生成并保存在bcrypt哈希值中。

工作流程

  • 密码存储
js
密码 → 加盐 → 多轮哈希 → 存储结果
  • 验证密码
js
输入密码 → 解析该账号的 bcrypt hash 中的 salt 和 cost → 重新计算 → 比较