MD5 被王小云攻破已经 20 年了,SHA1 被 Google 攻破也快 10 年了。什么是哈希碰撞?生日悖论和碰撞攻击有什么关系?数字签名为什么对哈希值签名?本文把哈希碰撞的数学原理、攻击历史和安全意义讲清楚。
什么是哈希碰撞
哈希碰撞(Hash Collision)指两个不同的输入,产生了相同的哈希值。
输入 A ≠ 输入 B
但 hash(A) = hash(B)
因为哈希函数的输出长度是固定的(比如 SHA256 是 256 位),而输入可以是任意长度。根据鸽巢原理——无限个鸽子飞进有限个鸽笼,必然有至少两只鸽子挤在同一个笼子里。碰撞是必然存在的,只是找到它的难度不同。
生日悖论:碰撞概率的数学基础
生日悖论(Birthday Paradox):在一个 23 人的房间里,有两个人同一天生日的概率超过 50%。
直觉上觉得不可思议——23 个人、365 天,概率应该很低吧?但计算一下:
n 个人中至少两个人生日相同的概率:
P(n) = 1 – 365/365 × 364/365 × 363/365 × … × (365-n+1)/365
n = 23 → P ≈ 50.7%
n = 57 → P ≈ 99%
n = 70 → P ≈ 99.9%
关键直觉:不是"我和你同一天生日"的概率,而是"任意两个人同一天生日"的概率。 23 个人有 23×22/2 = 253 对组合,每对都有可能匹配。
推广到哈希碰撞
对于 N 位输出的哈希函数(有 2^N 种可能的输出),找到一对碰撞的期望计算量约为 2^(N/2) 次:
| MD5 | 128 位 | 2^64 ≈ 1.8×10^19 次 | 现代 GPU 集群几年 |
| SHA-1 | 160 位 | 2^80 ≈ 1.2×10^24 次 | 理论上可行 |
| SHA-256 | 256 位 | 2^128 ≈ 3.4×10^38 次 | 不可行 |
| SHA-512 | 512 位 | 2^256 ≈ 1.2×10^77 次 | 宇宙级不可行 |
生日攻击是暴力碰撞的理论下界。但实际的密码分析攻击(利用哈希函数的内部结构缺陷)效率远高于生日攻击。
两种碰撞类型
1. 碰撞攻击(Collision Attack)
攻击者找到任意两个不同的输入 A 和 B,满足 hash(A) = hash(B)。
攻击者目标:找到 A ≠ B,hash(A) = hash(B)
难度:2^(n/2)(生日攻击)
应用场景:
– 伪造数字签名(找一个合法文件和一个恶意文件哈希相同)
– 证书伪造
2. 第二原像攻击(Second Preimage Attack)
给定一个已知输入 A,攻击者找到另一个不同的输入 B,满足 hash(A) = hash(B)。
攻击者目标:给定 A,找到 B ≠ A,hash(A) = hash(B)
难度:2^n(暴力枚举)
应用场景:
– 给定一个已知文件,找到另一个文件有相同哈希
– 比碰撞攻击难得多
碰撞攻击比第二原像攻击容易得多——因为碰撞攻击是"找任意一对",第二原像是"找指定的一个"。
MD5 碰撞攻破史
2004 年:王小云的理论突破
中国密码学家王小云团队在 CRYPTO 2004 会议上宣布:找到了 MD5 的完整碰撞攻击方法。
在此之前,学术界普遍认为 MD5 的碰撞攻击复杂度约为 2^64(生日攻击下界),实际不可行。王小云的分析将碰撞复杂度降到了 2^39 次运算——在普通计算机上几小时就能找到一对碰撞。
她的方法叫差分密码分析(Differential Cryptanalysis)——精心构造两个输入,它们的差异在哈希函数的多轮运算中被"控制",最终在输出处抵消。
2008 年:伪造 SSL 证书
2008 年,研究人员利用 MD5 碰撞攻击,伪造了一个合法的 CA 证书:
构造两个证书签名请求(CSR):
CSR-A: 正常域名 → 向 CA 申请证书 → CA 用 MD5 签名 → 得到合法证书
CSR-B: 恶意域名 → 有相同的 MD5 值 → 同样的签名也合法
结果:攻击者用 CSR-A 拿到 CA 签名,把签名装到 CSR-B 上
→ 浏览器信任了一个恶意网站的证书
这个事件直接推动了业界从 MD5 迁移到 SHA256。
2012 年:火焰病毒(Flame)
Flame 是一个复杂的间谍软件,它用 MD5 碰撞攻击伪造了微软的代码签名证书,让恶意程序看起来像微软官方发布的。
Flame 病毒的数字签名:
– 证书颁发者: Microsoft Terminal Services Licensing
– 签名算法: md5RSA
– 利用 MD5 碰撞伪造了证书链
微软不得不紧急发布安全公告,禁用 MD5 签名的证书。
SHA-1 碰撞攻破史
2005 年:理论攻击
王小云团队再接再厉,公布了 SHA-1 的理论碰撞攻击,复杂度约 2^69 次运算。虽然还不具备实战能力,但 SHA-1 的安全性开始被质疑。
NIST 随后宣布:2010 年之后联邦机构不再使用 SHA-1。
2017 年:SHAttered——Google 的实战碰撞
Google 和 CWI Amsterdam 联合公布了 SHAttered 攻击——第一个公开的 SHA-1 碰撞实例。
他们生成了两个内容不同但 SHA-1 相同的 PDF 文件:
文件 A: shattered-1.pdf → SHA-1: 38762cf7f55934b34d179ae6a4c80cadccbb7f0a
文件 B: shattered-2.pdf → SHA-1: 38762cf7f55934b34d179ae6a4c80cadccbb7f0a
两个 PDF 内容不同,但 SHA-1 哈希完全相同。
这次攻击用了什么资源?
- 计算量:约 9,223,372,036,854,775,808(2^63)次 SHA-1 运算
- 用 Google 的计算资源花了约一年时间
- 相当于单个 GPU 算 100 年
SHAttered 的意义:SHA-1 不再是理论上不安全,而是实战中可以被攻破。
2020 年:选择前缀碰撞
2020 年,研究人员公布了更强大的 SHA-1 选择前缀碰撞(Chosen-Prefix Collision)攻击,复杂度降至 2^63.1 次。
选择前缀碰撞意味着攻击者可以自由选择两个文件的前缀(比如两份不同的合同正文),然后计算后缀使两者哈希相同。这比任意碰撞威胁大得多——可以构造有实际意义的碰撞文件。
SHA-256 安全吗?
目前(2026 年)SHA-256 仍然安全:
- 没有公开的 SHA-256 碰撞攻击
- 最好的理论攻击也只是在弱化版本上取得进展
- 2^128 的碰撞抗性对于任何实际应用都足够
量子计算对 SHA-256 的影响:
- Grover 算法可以将暴力搜索的速度从 2^n 降到 2^(n/2)
- 但 SHA-256 的 2^128 碰撞抗性即使打对折,仍然是 2^64——足够安全
- 相比之下,RSA/ECC 等非对称加密受量子威胁更大(Shor 算法)
数字签名为什么对哈希值签名
数字签名(如 RSA、ECDSA)不对原文签名,而是先计算原文的哈希,再对哈希值签名。
签名过程:
原文 → SHA256 → 哈希值 → RSA 私钥签名 → 签名
验证过程:
原文 → SHA256 → 哈希值
签名 → RSA 公钥验证 → 哈希值
两者对比 → 一致则验证通过
两个原因:
碰撞攻击对数字签名的威胁:如果哈希算法存在碰撞,攻击者可以:
1. 构造两个内容不同但哈希相同的文档:Doc-A 和 Doc-B
2. 让受害者对 Doc-A 签名(比如一份正常合同)
3. 把签名粘到 Doc-B 上(比如一份对攻击者有利的合同)
4. 签名验证仍然通过——因为哈希相同
这就是为什么 MD5 和 SHA-1 被攻破后,所有数字签名系统都必须迁移到 SHA-256。
各算法碰撞抗性时间线
1992 MD5 发布
2004 王小云攻破 MD5(理论)
2005 SHA-1 理论攻击
2008 MD5 伪造 SSL 证书
2012 Flame 病毒用 MD5 伪造微软签名
2017 SHAttered 攻破 SHA-1(实战)
2020 SHA-1 选择前缀碰撞
2026 SHA-256 仍是安全标准
在线验证
理解哈希碰撞最好的方式是亲自验证雪崩效应——输入的微小变化导致输出的巨大变化,这是抗碰撞性的直观体现。
可以在 盘子工具站哈希计算工具 上做这种验证——
第一步:输入 Hello World,记录 SHA256 结果。 
第二步:把 World 改成 world(W 改小写),再算一次。两个哈希值从第一个字符就完全不同——这就是雪崩效应。
第三步:你可以做一个"碰撞寻找"的小实验——用工具尝试各种输入,看能不能找到两个不同输入有相同的哈希值。对于 MD5,理论上需要尝试 2^64 次才能找到一对碰撞——这在个人电脑上几乎不可能,但这也正好说明了哈希的抗碰撞性。
工具同时输出五种算法的结果,你可以对比五种算法的雪崩效应强度——所有算法都有强雪崩效应,但安全性不同。所有计算在浏览器本地完成,不上传服务器。
网硕互联帮助中心



评论前必须登录!
注册