MD5 和哈希是什么:文件校验、密码存储和常见误解
下载软件时,官网常在下载链接旁边写着一串 SHA-256 值;数据库里的用户密码字段是一串看不懂的字符;网上还有人说“MD5 已经被破解了”。这些都和“哈希”有关。这篇文章用尽量少的数学,讲清哈希是什么、能做什么、不能做什么。
一、哈希函数的四个特点
哈希函数把任意长度的数据变成一个固定长度的“指纹”。比如 SHA-256 无论输入是一个字还是一个 4 GB 的文件,输出都是 256 位,通常写成 64 个十六进制字符。好的哈希函数有这些特点:
- 确定性:同样的输入,永远得到同样的输出。
- 雪崩效应:输入改动一个字符,输出几乎完全不同。
- 单向:从输出无法反推出输入。
- 抗碰撞:很难找到两个不同的输入得到相同输出。
例如字符串 abc 的 MD5 是 900150983cd24fb0d6963f7d28e17f72,SHA-256 是 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。这两个值是公开的标准测试向量,你可以用任何哈希工具验证。
二、哈希不是加密,也不是编码
- 编码(如 Base64):可以完全还原,目的是换一种表示方式。
- 加密(如 AES):有密钥的人可以还原,目的是保密。
- 哈希:设计上不可还原,目的是校验和比对。
说“把密码 MD5 加密”其实不准确,应该说“对密码做哈希”。
三、用途一:校验文件完整性
下载大文件后,计算它的哈希,与官网公布的值比对,一致就说明文件没有在下载过程中损坏,也没有被替换(前提是官网页面本身可信,并通过 HTTPS 访问)。
# Windows(PowerShell)
Get-FileHash .\setup.exe -Algorithm SHA256
# macOS
shasum -a 256 setup.dmg
# Linux
sha256sum setup.iso
比对时不必逐个字符看,复制两个值到文本工具里查找,或者只要有一个字符不同,整串就会差别很大,比较开头和结尾各 8 位基本就能发现问题,但严谨起见应完整比对。
四、为什么 MD5、SHA-1 不再安全
MD5 输出 128 位,SHA-1 输出 160 位。研究人员早已找到构造 MD5 碰撞的实用方法,2017 年也公开了 SHA-1 的实际碰撞实例。这意味着攻击者可以制造两个内容不同但哈希相同的文件。因此:
- 数字签名、证书、安全校验等场景,不应再使用 MD5 和 SHA-1,应使用 SHA-256 及以上。
- MD5 仍然可以用于非安全场景,例如快速判断两个文件是否重复、缓存键、分片校验等,前提是不存在恶意攻击者。
五、用途二:存储密码
网站不应保存用户的明文密码,而是保存密码的哈希值,登录时把用户输入的密码同样做哈希再比对。但直接用 MD5 或 SHA-256 存密码是不够的:
- 彩虹表:常见密码的哈希值早已被大量预先计算好,查表即可反查。
- 速度太快:通用哈希函数设计得很快,攻击者用显卡每秒能尝试海量密码。
正确做法是使用专门的密码哈希算法,如 Argon2、bcrypt、scrypt 或 PBKDF2。它们会:
- 为每个用户生成随机的盐(salt),同样的密码因盐不同得到不同结果,彩虹表失效;
- 故意设计得很慢,并且可以调整计算成本,让暴力破解代价大幅提高。
主流编程语言和框架都有现成的实现,直接使用即可,不要自己设计“MD5 套 MD5”之类的方案。
六、其他常见用途
- Git:每个提交、文件都由哈希值标识,Git 正在从 SHA-1 向 SHA-256 过渡。
- 去重:网盘、备份软件用哈希判断文件是否已存在。
- HMAC:在哈希中加入密钥,用于接口签名,验证请求未被篡改。
- 数据分片:按哈希值把数据分配到不同服务器。
七、常见误解
- “MD5 可以解密”:网上的“MD5 解密”其实是查已知结果的数据库,只对常见、简单的输入有效。
- “哈希值相同,文件一定相同”:对安全哈希来说几乎可以这样认为,但对 MD5 而言,攻击者可以刻意构造碰撞。
- “哈希值长一点就更安全”:安全性取决于算法本身,不能把 MD5 结果拼两遍当作更强的哈希。
八、在线计算哈希
本站新增了 哈希计算工具,可以计算文本或本地文件的 MD5、SHA-1、SHA-256、SHA-384、SHA-512,并与给定值比对。文件在浏览器中本地读取计算,不会上传。哈希结果经常需要和 Base64 互转(例如某些接口用 Base64 表示 SHA-256),可以配合 Base64 编解码工具 使用。