主题
MD5 已经不安全了,为什么还到处在用
「MD5 不安全,别用了」——这话没错,但下载页上给的校验值至今很多还是 MD5。两件事其实不矛盾,因为它们防的根本不是同一种问题。

打开「文件哈希校验」看到的初始界面。在浏览器本地完成、数据不离开浏览器,免费。
先分清两种威胁
意外损坏:文件在传输或存储中出错。网络丢包、硬盘坏道、下载中断后续传错位。这种错误是随机的,没有智能,不会挑算法的弱点。
恶意篡改:有人故意改了文件,还要让校验值看起来没变。这是有目标、有算力的对手。
MD5 挡得住第一种,挡不住第二种。而下载页给校验值,绝大多数时候要解决的就是第一种。
MD5 到底怎么被攻破的
需要区分两类攻击,它们的严重程度差很远:
| 攻击类型 | 含义 | MD5 现状 |
|---|---|---|
| 碰撞攻击 | 攻击者自己构造两个哈希相同的文件 | 已被攻破,普通电脑几秒可完成 |
| 原像攻击 | 给定一个哈希值,反推出能产生它的文件 | 仍未被有效攻破 |
关键区别是:碰撞攻击要求攻击者能同时控制两个文件。他可以造出「正常版」和「带后门版」两个哈希相同的程序,把正常版拿去送检,把带后门版发给你。
但如果文件是别人给定的、他改不了原文件——比如官方发布的安装包已经存在、哈希已经公布——他没法凭空造出一个哈希相同的恶意文件。这就是为什么 MD5 用于校验已公布文件的完整性时,实际风险远小于标题党说的那样。
即便如此,SHA-256 的计算成本在今天已经低到可以忽略,新场景没有任何理由继续选 MD5。
三个算法怎么选
| 算法 | 输出长度 | 状态 | 建议 |
|---|---|---|---|
| MD5 | 128 位(32 个十六进制字符) | 碰撞已攻破 | 仅用于校验意外损坏;兼容旧系统 |
| SHA-1 | 160 位(40 个字符) | 碰撞已攻破(2017 年) | 不要用于新场景 |
| SHA-256 | 256 位(64 个字符) | 安全 | 默认选它 |
一句话:新场景一律 SHA-256;遇到只给 MD5 的下载页,算 MD5 对一下也比不校验强。
校验值对不上,先别慌
实际操作中,校验失败十有八九不是被篡改了,而是这几种情况:
下载不完整。 最常见。文件大小对不上就基本可以确定,重新下载即可。
比错了对象。 有些发布页同时给出压缩包和解压后文件的哈希,或者给了多个平台的版本。确认你算的和页面上标的是同一个文件。
换行符被改写。 文本文件在 Windows 和 Linux 之间传递时,如果经过了会转换换行符的工具(某些 Git 配置、FTP 的文本模式),内容变了哈希自然就变了。二进制文件不受影响。
大小写差异。 十六进制哈希值大小写不敏感,A3F 和 a3f 是同一个值。有些工具输出大写、有些小写,肉眼比对时容易看岔。
一个常见的误用:拿它存密码
顺带说一个和文件校验无关、但同源的错误:用 MD5(或 SHA-256)存用户密码。
问题不在于算法被攻破,而在于它们太快了。哈希算法为文件校验而设计,追求的就是快——一台普通显卡每秒能算几十亿次 SHA-256。这个优点用在密码上就成了致命缺点:攻击者拿到数据库后,可以用同样的速度暴力穷举。
密码要用专门的慢哈希:bcrypt、scrypt、Argon2。它们故意设计得慢且吃内存,并且每个密码配一份随机盐,让预先算好的彩虹表失效。
所以「用 SHA-256 代替 MD5 存密码」并没有解决问题,只是把一个快算法换成了另一个快算法。
怎么算
文件哈希校验 一次性给出 MD5、SHA-1、SHA-256 三个值,也可以直接粘贴官网给的校验值做比对——工具会告诉你匹配与否,不用自己盯着 64 个字符逐位对。
计算在浏览器本地完成,文件不上传。这对校验类工具是必要的:为了验证一个文件没被动过而先把它上传到某个服务器,本身就与目的相悖。
校验只能证明文件与发布者公布的一致。如果发布渠道本身被入侵、连哈希值一起被替换,校验也无能为力——所以哈希值要从可信来源获取,最好与文件本身不同源。