4. 哈希与消息认证:SHA-2/SHA-3家族、HMAC构造、哈希长度与碰撞安全性、SM3国密算法
哈希函数,说白了就是数据的「数字指纹」。你给它任意长度的输入,它吐出一段固定长度的摘要。这个过程不可逆,而且理论上不同的输入应该得到不同的摘要。嗯,理论上是这样。
我在实际做安全审计时,见过不少因为哈希选型翻车的案例。有人图快用MD5做签名,结果被碰撞攻击打得满地找牙。也有人把SHA-1当宝贝供着,直到Google公开了SHAttered碰撞实例才慌忙升级。所以这一章,咱们把哈希家族、HMAC构造、以及国密SM3彻底捋一遍。
4.1 SHA-2家族:当前的主力军
SHA-2是NIST在2001年发布的标准,至今仍是互联网的基石。它包含SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224和SHA-512/256这六种变体。你想想看,为什么搞这么多长度?
核心原因就一个:适配不同的安全等级和平台。SHA-256输出32字节,适合大多数场景;SHA-512输出64字节,在64位CPU上反而比SHA-256更快——因为它的运算字长是64位,跟CPU寄存器宽度一致。我在给金融核心系统做方案时,就强制要求使用SHA-256以上,SHA-1一律禁用。
SHA-2的内部结构
SHA-256的流程大致分三步:
- 填充:在消息末尾补一个'1'位,然后补'0'直到长度模512等于448,最后附加64位的原始长度值。
- 分块:把填充后的消息切成512位的块。
- 压缩:每个块经过64轮迭代,更新8个32位工作变量。
说白了就是「分块-迭代-压缩」的经典Merkle-Damgård结构。不过SHA-2有个小毛病——长度扩展攻击。什么意思?就是如果你知道H(M),即使不知道M本身,也能算出H(M || padding || extra)。这很危险,所以后面才有了HMAC和SHA-3。
4.2 SHA-3家族:新一代的胜出者
SHA-3是NIST在2015年选定的新标准,它跟SHA-2完全不是一个路数。SHA-3用的是Keccak算法,基于海绵结构(Sponge Construction),而不是Merkle-Damgård。
海绵结构的好处是:
- 天然抵抗长度扩展攻击
- 可以输出任意长度的摘要(可扩展输出函数,XOF)
- 在硬件实现上更高效
SHA-3家族包括SHA3-224、SHA3-256、SHA3-384、SHA3-512,以及两个可扩展输出函数SHAKE128和SHAKE256。我在做物联网固件签名时,就特别喜欢用SHAKE128——因为它可以按需输出256位或更长的摘要,灵活性极高。
4.3 哈希长度与碰撞安全性
哈希函数的安全性,核心看两个指标:抗碰撞性和抗原像性。咱们重点说碰撞。
根据生日悖论,找到碰撞的期望工作量大约是2^(n/2)次哈希计算,其中n是输出比特数。所以:
| 哈希算法 | 输出长度 | 碰撞安全强度 | 当前状态 |
|---|---|---|---|
| MD5 | 128位 | 2^64(已被攻破) | ❌ 彻底禁用 |
| SHA-1 | 160位 | 2^80(已被攻破) | ❌ 彻底禁用 |
| SHA-256 | 256位 | 2^128 | ✅ 安全 |
| SHA-384 | 384位 | 2^192 | ✅ 安全 |
| SHA-512 | 512位 | 2^256 | ✅ 安全 |
| SM3 | 256位 | 2^128 | ✅ 安全 |
你可能会问:2^128的碰撞强度够用吗?我直接说结论:以目前人类的计算能力,2^128是天文数字。就算你用上全球所有的算力,也要算到宇宙热寂。所以SHA-256的碰撞安全性,在可预见的未来是牢不可破的。
4.4 HMAC构造:消息认证码的正确姿势
哈希函数本身不提供认证功能。你收到一段消息和它的哈希值,怎么确认这哈希值没被篡改?答案是加盐——也就是密钥。HMAC(Hash-based Message Authentication Code)就是干这个的。
HMAC的标准定义是:
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
其中:
K'是经过填充或哈希处理的密钥ipad是0x36重复的字节串opad是0x5C重复的字节串||表示拼接
为什么要搞这么复杂?直接H(K || m)不行吗?
不行。我曾经在早期的一个项目中就犯过这个错——直接用H(K || m)做消息认证。结果被安全审计发现存在长度扩展攻击漏洞。攻击者可以在不知道密钥的情况下,构造出合法的H(K || m || padding || extra)。嗯,那次被批得很惨。
HMAC通过内外两次哈希,彻底解决了这个问题。它的安全性证明依赖于底层哈希函数的伪随机函数性质,而不是抗碰撞性。所以即使有一天SHA-256的碰撞被攻破,HMAC-SHA-256仍然可能是安全的。
4.5 SM3国密算法:中国的国家标准
SM3是中国国家密码管理局发布的哈希算法标准,输出256位摘要。它的设计思路跟SHA-256类似,但细节上有不少差异:
- 消息分组长度也是512位,输出256位
- 压缩函数有64轮,但每轮的布尔函数和置换跟SHA-256不同
- 使用了16个32位寄存器的线性反馈移位寄存器(LFSR)来生成每轮的消息字
SM3的安全性经过国内外的广泛分析,目前没有发现实质性漏洞。它的碰撞安全强度也是2^128,跟SHA-256相当。
我在做政务系统等保三级测评时,遇到过必须使用国密算法的场景。SM3配合SM2(椭圆曲线公钥密码)和SM4(分组密码),构成了完整的国密套件。如果你做的是面向政府或金融的系统,这块是绕不过去的。
4.6 知识体系总览
下面这张图把本章的核心逻辑串起来了。你可以看到哈希家族的分支、HMAC的构造位置、以及SM3的定位。
4.7 实践中的选择建议
说了这么多理论,最后给点实在的。如果你现在要设计一个系统,哈希部分怎么选?
- 通用场景:SHA-256。成熟、高效、安全,所有平台都支持。
- 新协议设计:SHA3-256或SHAKE128。避免长度扩展攻击,设计更现代。
- 国内合规:SM3。等保、密评、政务系统绕不开。
- 消息认证:HMAC-SHA256。密钥长度32字节,定期轮换。
- 密码哈希存储:别用普通哈希!用bcrypt、scrypt或Argon2。这个后面章节会细讲。