哈希函数是现代密码学的基石之一,它将任意长度的输入映射为固定长度的摘要,广泛应用于数据完整性校验、数字签名、密码存储等场景。然而,哈希函数的安全性并非一成不变 —— 从 MD5 的彻底沦陷到 SHA-1 的逐步淘汰,再到 SHA-2 的广泛使用与 SHA-3 的崛起,每一次迭代都伴随着对碰撞攻击和结构缺陷的深刻反思。
MD5 的兴衰:从广泛应用到完全破解
MD5(Message-Digest Algorithm 5)由 Ron Rivest 于 1992 年设计,输出 128 位摘要。在其诞生后的十余年间,MD5 几乎成为数据完整性校验的事实标准,被广泛应用于软件分发、SSL 证书、文件校验等场景。
然而,MD5 的安全隐患逐渐暴露。2004 年,王小云教授团队在国际密码学会议上宣布找到 MD5 的碰撞攻击方法,能够在数小时内找到两个具有相同哈希值的不同消息。这一突破标志着 MD5 在密码学意义上的死亡。后续研究进一步降低了攻击成本,使得 MD5 碰撞可以在普通计算机上秒级完成。
MD5 的脆弱性源于其设计缺陷:其 128 位的输出长度在现代计算能力下已不足以抵抗生日攻击(Birthday Attack),而算法内部的压缩函数结构也存在可被利用的弱点。
SHA-1 的退场:SHAttered 攻击与行业响应
SHA-1(Secure Hash Algorithm 1)于 1995 年由 NSA 设计并发布,输出 160 位摘要,旨在替代 MD5。尽管 SHA-1 在设计上修复了 MD5 的部分缺陷,但其 160 位的输出长度和与 MD5 相似的 Merkle-Damgård 结构仍埋下了隐患。
2017 年,Google 研究团队宣布成功实施 SHAttered 攻击,首次在实践中生成了两个不同的 PDF 文件具有相同的 SHA-1 哈希值。这次攻击耗费了 6500 年的 CPU 计算时间(通过 GPU 集群加速实际耗时约两个月),证明了 SHA-1 的碰撞攻击已从理论可能变为工程现实。
此后,主流浏览器和证书机构加速淘汰 SHA-1。Chrome 于 2017 年开始标记使用 SHA-1 签名的证书为不安全,微软和 Mozilla 也相继跟进。到 2020 年,SHA-1 在 TLS 证书中的使用已降至接近零。
SHA-2 的现状:安全性与长度扩展隐患
SHA-2 家族于 2001 年发布,包含 SHA-256、SHA-384、SHA-512 等变体,目前仍是业界最广泛使用的哈希函数。SHA-256 输出 256 位摘要,在可预见的未来内能够抵抗生日攻击(需要约 2^128 次操作才能找到碰撞)。
然而,SHA-2 继承了 Merkle-Damgård 结构,这一结构存在一个鲜为人知但影响深远的弱点:长度扩展攻击(Length Extension Attack)。
在 Merkle-Damgård 结构中,消息被分块处理,每块的输出作为下一块的输入,最终的块输出经过截断后成为哈希值。问题在于,哈希值本身包含了内部状态的完整信息。攻击者可以在不知道原始消息内容的情况下,计算出 Hash (message || padding || suffix) 的值。
这一特性在特定场景下可被利用。例如,在某些简单的消息认证实现中,如果服务器验证的是 Hash (secret || data),攻击者可以在不知道 secret 的情况下,构造出 Hash (secret || data || padding || malicious_data) 的有效值。
防御长度扩展攻击的标准做法是使用 HMAC(Hash-based Message Authentication Code),它通过嵌套哈希的方式消除了长度扩展的风险。另一个选择是 SHA-3,其海绵结构天然免疫此类攻击。
SHA-3 的设计哲学:海绵结构与免疫性
SHA-3 于 2015 年正式发布,其底层算法为 Keccak,由 Guido Bertoni、Joan Daemen、Michaël Peeters 和 Gilles Van Assche 设计。值得注意的是,SHA-3 的推出并非因为 SHA-2 已被破解,而是作为一套基于完全不同设计原则的备用方案。
Keccak 采用海绵结构(Sponge Construction),与 Merkle-Damgård 有本质区别。海绵结构分为两个阶段:吸收(Absorb)和挤出(Squeeze)。在吸收阶段,输入块与状态进行异或操作后进入置换函数;在挤出阶段,从状态中提取输出块。这种设计使得内部状态的一部分永远不会直接暴露为输出,从而天然免疫长度扩展攻击。
此外,SHA-3 提供了可扩展输出函数(XOF),如 SHAKE128 和 SHAKE256,允许输出任意长度的摘要,这在某些需要长摘要的场景中提供了灵活性。
工程实践建议:选型与迁移策略
基于上述分析,以下是可落地的工程建议:
新系统开发:优先选用 SHA-3-256 或 SHAKE128。SHA-3 的安全性经过充分验证,且免疫长度扩展攻击,简化了安全设计。
遗留系统兼容:如必须使用 SHA-2,务必使用 HMAC-SHA256 而非裸 SHA-256。HMAC 的嵌套结构消除了长度扩展风险。
数字证书与签名:使用 SHA-256 或 SHA-384,避免使用已淘汰的 SHA-1。证书链中的所有中间证书也应升级至 SHA-2 或更高。
密码存储:不要直接使用任何 SHA 系列哈希存储密码。应使用专门设计的密码哈希函数,如 Argon2、scrypt 或 bcrypt,这些算法包含盐值和计算成本因子,能够抵抗彩虹表攻击和硬件加速暴力破解。
迁移优先级:首先替换面向公网的系统(如 TLS 证书、API 签名),然后是内部关键基础设施,最后是内部非敏感系统。迁移过程中注意保持向后兼容性,避免服务中断。
哈希函数的演进史是一部密码学攻防的缩影。从 MD5 的彻底沦陷到 SHA-1 的被迫退场,再到 SHA-2 的广泛使用与 SHA-3 的新范式,每一次迭代都在提醒我们:安全是一个动态过程,而非静态结果。理解这些设计权衡和潜在陷阱,是构建安全系统的必要基础。
参考来源
- NIST FIPS 180-4 Secure Hash Standard
- NIST FIPS 202 SHA-3 Standard
- Wang et al., "Collisions for Hash Functions MD4, MD5, RIPEMD and HAVAL" (2004)
- CWI/Google, "Announcing the first SHA-1 collision" (2017)
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。