哈希函数
哈希函数是一种把任意长度数据 → 固定长度输出 的算法
特点
固定长度输出
无论输入多长,输出长度固定。
例如:
- SHA256 → 256 位(32 字节)
- MD5 → 128 位(16 字节)
不可逆
无法从哈希值反推出原始数据。
js
A → hash
但不能 hash → A雪崩效应
输入哪怕改一个字符,结果都会完全不同。
js
hello
→ 2cf24d...
hellO
→ 872e4e...一致性
相同的输入,相同的算法,必定具有相同的输出
常见哈希算法
| 算法 | 长度(HEX) | 是否安全 | 说明 |
|---|---|---|---|
| MD5 | 32 | ❌ 不安全 | 已被破解 |
| SHA256 | 64 | ✅ 安全 | 常用 |
| SHA512 | 128 | ✅ 安全 | 更强 |
哈希是不安全的
虽然哈希值不可逆,但是哈希具有一致性,因此通过暴力枚举,就有可能得到原始值。
因为哈希输出是固定长度,而输入是无限可能。当输入数量超过输出空间,就一定会出现碰撞(哈希碰撞)。(例如 SHA256 只有 2²⁵⁶ 种结果)。
哈希碰撞在数学上必然存在,但在工程上可以忽略。
应用
密码存储
数据库通常不会存储明文密码,会将原始密码转为哈希值存入数据库。
js
password → hash → 存数据库验证时
js
输入密码 → hash → 对比数据库文件完整性校验
下载文件后:
js
文件 → 计算 hash
对比官方 hash一致 说明文件未被篡改
bcrypt
bcrypt 是一种专门用于密码存储的慢哈希算法。bcrypt 设计目标不是“快速算出哈希”,而是“让破解变得非常慢”。
bcrypt通常需要第三方库支持
原理
bcrypt 哈希值的特点是加密后的字符串包含了加密时的算法版本、成本因子、盐、和最终得到的哈希值
js
$2a$10$7mG.bF32bv36IBLetWB11O6zMAXe9Zc5P7cTkfgqTol7yVspl37Vajs
$算法版本$成本因子$盐值+哈希结果- 算法版本
表示 bcrypt 版本。
- 成本因子
成本因子来控制计算轮数。
js
cost = 10 →2^10→ 1024 次运算
cost = 12 →2^12→ 4096 次运算- 盐
bcrypt 会自动生成并保存在bcrypt哈希值中。
工作流程
- 密码存储
js
密码 → 加盐 → 多轮哈希 → 存储结果- 验证密码
js
输入密码 → 解析该账号的 bcrypt hash 中的 salt 和 cost → 重新计算 → 比较