MD5 和 SHA 有什么区别?校验文件与选算法看这篇
官网公布了一段 SHA-256,下载完的文件要怎么核对?数据库里存的密码哈希能不能反推回明文?MD5 现在到底还能不能用?这三个问题的答案都取决于同一个概念 —— 哈希函数能证明什么、不能证明什么。
- 哈希是单向的:从哈希值反推原文只能靠穷举,所以没有「解密哈希」这回事
- MD5 输出 32 位十六进制,SHA-1 是 40 位,SHA-256 是 64 位 —— 长度不同,不要互相比较
- MD5 与 SHA-1 已被证明可以人为构造碰撞,不能用于数字签名和证书,但做「文件是否损坏」的完整性校验仍然够用
- 同一个输入必然得到同一个输出;输入改变一个字符,输出就会完全不同
- 直接存哈希仍不安全:无盐的 MD5 可被彩虹表秒查,密码必须加盐并用慢哈希
#哈希函数能证明什么
哈希函数把任意长度的数据压成固定长度的摘要,且这个过程不可逆。 它的三条性质决定了所有用法:
- 确定性:同一份数据永远得到同一个结果,哪怕只有一个字节不同,结果也会面目全非。
- 单向性:只能从原文算哈希,不能从哈希算回原文。所谓「哈希破解」实际上是拿字典逐条去算再比对,属于穷举,不是数学上的反推。
- 抗碰撞:很难找到两份不同的数据拥有相同的哈希值。这条性质分强弱,也正是 MD5 与 SHA-256 的分水岭。
所以哈希值最适合回答「这份数据和预期的那份是不是同一份」——比如下载文件有没有损坏、传输有没有被改动。
#三种算法的长度与边界
先看长度,这决定了输出的形状,也决定了你能不能一眼看出对方用错了算法:
| 算法 | 输出位数 | 十六进制长度 | 现状 |
|---|---|---|---|
| MD5 | 128 位 | 32 个字符 | 可构造碰撞,仅适合完整性校验 |
| SHA-1 | 160 位 | 40 个字符 | 可构造碰撞(2017 年 SHAttered),不建议新用 |
| SHA-256 | 256 位 | 64 个字符 | 目前无实用碰撞,是通行选择 |
| SHA-512 | 512 位 | 128 个字符 | 更安全但更长,快于 SHA-256 的场景有限 |
MD5 现在不能用于数字签名、证书、代码签名、防篡改这类「对抗攻击者」的场景。攻击者可以构造两个内容不同但 MD5 相同的文件,让你的校验通过。做「文件是否完整」的校验(防传输损坏、防下载中断)它依然够用,因为那类错误是随机的,不是人为构造的。
#三步校验下载的文件
- 打开 SHA 系列哈希(要算 MD5 就用 MD5 加密),选择算法。
- 把文件拖进上传区,工具会在浏览器本地读取并计算,文件不会上传。
- 把结果与官网公布的校验值逐位对比,包括大小写规则。完全一致才说明文件完整。
核对时不要只看「前几位像不像」。哈希只要有一个字符不同就是完全不同的一份数据,必须完整比对。用 文本差异对比 把两个哈希串并排放,比人眼扫更可靠。
命令行习惯的人可以直接用系统自带工具,结果应当与在线工具完全一致:
# macOS / Linux
shasum -a 256 package.tar.gz
md5sum package.tar.gz
# Windows PowerShell
Get-FileHash package.tar.gz -Algorithm SHA256#为什么「加盐」是必须的
无盐的哈希不适合存密码,原因不是算法弱,而是输入空间太小。 常用密码只有几十万种,攻击者预先算好一张「明文 → MD5」的对照表(彩虹表),查询一个哈希值只需要毫秒级。
加盐的做法是给每个用户的密码拼接一段随机字符串再算哈希,让同一个人在不同站点、不同账户的哈希完全不同:
| 存储方式 | 攻击者拿到数据库后 | 结论 |
|---|---|---|
md5(password) | 查彩虹表,常用密码秒出 | 不可用 |
md5(password + 固定盐) | 全站共用一个盐,一次破解全站通用 | 不够 |
md5(password + 每用户随机盐) | 必须逐个用户穷举 | 勉强,但 MD5 太快仍是劣势 |
| bcrypt / scrypt / Argon2 | 算法本身刻意变慢,穷举成本极高 | 推荐做法 |
关键不在于「用了哪种哈希算法」,而在于算法是否足够慢。MD5 和 SHA-256 都为速度而设计,用来存密码反而成了缺点。密码存储请用 bcrypt、scrypt 或 Argon2 这类可调工作量的算法。
#别把 UUID 当成哈希
这两个东西经常一起出现,但完全不同:
- 哈希是对已有数据的摘要,输入相同输出必然相同,长度固定。
- UUID 是凭空生成的标识符,UUID / GUID 生成 用它给数据库行、会话、请求分配唯一 ID。
如果你需要的是「唯一编号」,用 UUID;如果需要的是「校验这段数据有没有变」,用哈希。用哈希当 ID 会遇到两个风险:一是理论上可能碰撞(虽然概率极低),二是如果 ID 由用户输入算出,攻击者可以预测。
#常见场景对照
| 你要做的事 | 用哪个 | 注意 |
|---|---|---|
| 校验下载文件是否完整 | SHA 系列哈希 选 SHA-256 | 与官方公布值逐位比对 |
| 项目里历史遗留的 MD5 校验 | MD5 加密 | 兼容旧系统可用,新项目别再引入 |
| 给接口参数做签名 | SHA-256 及以上 | 必须配合密钥(HMAC),单纯哈希不防伪造 |
| 存用户密码 | bcrypt / scrypt / Argon2 | 不要用本站工具处理真实密码 |
| 生成唯一 ID | UUID / GUID 生成 | 这不是哈希 |
| 编码传输内容 | Base64 编码解码 | 也不是哈希,可逆 |
#常见问题
#哈希可以解密吗?
不能。不存在「哈希解密」这个操作。市面上号称能解 MD5 的网站,实际做法是预先存好大量「常见字符串 → 哈希」的对照表,你的哈希恰好命中就显示原文,没命中就查不到。所以短、简单的密码「能解出来」不是因为算法被破了,而是因为字典里有。
#MD5 到底还能不能用?
分场景。做完整性校验(文件传输有没有损坏、下载有没有中断)可以用,这类错误是随机发生的,不是攻击者构造的。做安全相关的事(签名、证书、防篡改、密码存储)不能用,已经有公开的碰撞构造方法。
#为什么同一个文件在 Windows 和 Linux 上算出来的哈希不一样?
先怀疑文件本身不同:Windows 下用文本模式传输会把换行符 \n 改成 \r\n,内容变了哈希自然不同。确认用二进制模式重新传输。另外极少数情况是两条命令默认算法不同,把算法参数显式写出来即可。
#SHA-256 比 MD5 慢很多吗?
在现代 CPU 上两者的差距对日常使用没有影响。对一个几十 MB 的文件,SHA-256 大概比 MD5 慢一倍左右,仍然是毫秒到几百毫秒的量级。选择依据应该是安全性,不是速度。
#哈希长度越长越安全吗?
在一定范围内是这样,但有上限。SHA-512 比 SHA-256 长、理论强度更高,代价是结果更长、存储和传输都更占空间。目前实际工程中以 SHA-256 为主流,除非有特殊合规要求,不需要刻意选更长的。