哈希函数与消息认证
密码学哈希把任意输入映射成固定长度的指纹。本章讲密码学哈希的三个性质、SHA-2/SHA-3、长度扩展攻击与 HMAC、以及密码存储的慢哈希——先分清它与哈希表用的哈希(→ 哈希表)。
| 哈希表的哈希 | 密码学哈希 | |
|---|---|---|
| 目标 | 快 + 均匀 | 安全性质 |
| 抗碰撞 | 不要求 | 必须 |
| 抗原像 | 不要求 | 必须 |
| 速度 | 越快越好 | 慢有时是特性(密码存储) |
MD5/SHA-1 已被碰撞攻击攻破(MD5 2004、SHA-1 2017 实际碰撞):用于签名与证书已不安全;用于非对抗场景(去重、校验)勉强可用——新代码一律 SHA-256 及以上。
密码学哈希的三个性质
Section titled “密码学哈希的三个性质”- 抗原像(preimage):给哈希值 ,找不到输入 使 ——不可逆;
- 抗第二原像:给 ,找不到 使 ;
- 抗碰撞(collision):找不到任何 使 。
生日界(birthday bound): 位哈希的抗碰撞强度约 ——256 位哈希给出 128 位碰撞强度(→ 公钥密码与密钥交换)。
SHA-2(SHA-256/512)与 SHA-3(Keccak,结构不同——海绵结构)是现代标准;BLAKE3 更快。
长度扩展攻击与 HMAC
Section titled “长度扩展攻击与 HMAC”Merkle–Damgård 结构(SHA-256 等)的可预测性带来长度扩展攻击:知道 与 、(不知道 ),能直接计算 ——朴素 MAC(密钥拼在消息前)被攻破:攻击者伪造"密钥认证过"的扩展消息。
HMAC 修复了朴素 MAC 的长度扩展问题:
双层哈希让攻击者无法利用内部状态。HMAC 是消息认证的标准(TLS、JWT 的 HS256、API 签名):认证用 HMAC,别自己拼密钥。
MAC 的用途
Section titled “MAC 的用途”- 消息完整性 + 认证:接收方(持同一密钥)验证消息未被篡改且来自持有密钥的一方;
- 密钥派生:HKDF(基于 HMAC 的 KDF)从主密钥派生子密钥;
- AEAD 内部:GCM 的 GHASH 与 HMAC 是同一使命(完整性)的不同实现(→ 对称密码)。
密码存储:慢哈希
Section titled “密码存储:慢哈希”存密码不能用快速哈希——SHA-256 太快(GPU 每秒数十亿次),暴力破解与字典攻击毫不费力。密码存储应使用慢哈希(故意慢 + 内存难):
| 算法 | 特点 |
|---|---|
| bcrypt | 可调轮数,久经考验 |
| scrypt | 内存难(抗 GPU/ASIC) |
| Argon2(2015 竞赛冠军) | 内存 + 时间都可调,现代默认 |
三条纪律:
- 盐(salt):每用户随机盐,防彩虹表(预计算表失效);
- 慢哈希:Argon2id 调到"登录可接受的最慢"(约 100–500ms);
- 密码不行就 pepper(服务端全局密钥,存 HSM/KMS)加一层。
密码重置比密码恢复更安全:存不了明文就别想恢复,重置走邮件/OTP。
- 哈希表的哈希与密码学哈希是两回事:后者必须抗原像与碰撞
- MD5/SHA-1 已被碰撞攻击攻破;新代码 SHA-256+;生日界
- HMAC 修复了朴素 MAC 的长度扩展问题:认证用 HMAC 别自己拼密钥
- 存密码不能用快速哈希:Argon2/bcrypt + 每用户盐,调到登录可接受的最慢
- 密码不可恢复只可重置