杂记 › 技术笔记 › 下载的文件被篡改了吗?用MD5校验1分钟验明正身

下载的文件被篡改了吗?用MD5校验1分钟验明正身

去年冬天我给 NAS 做了次冷备份,两块 4TB 盘,rsync 跑了将近十一个小时,跑完只看了退出码是 0 就收工。两个月后要恢复一个记账用的压缩包,解压时报 unexpected end of archive——那个包本来 2.1GB,盘里只剩 1.4GB,中间某次写入悄悄断了。我没有任何办法证明其它三百多个包是好的。从那以后我的备份流程里多了一步:算完哈希、清单存到另一台机器上。哈希到底能证明什么、对哪一类问题无能为力,是那之后才弄清的。

一、哈希是内容的指纹,不是加密

MD5 把任意长度的数据压成 128 位、通常写成 32 个十六进制字符的一串。三个特性决定了它能做什么:输出定长,一个 3 字节文本和一个 4GB 镜像算出来的结果一样长;单向不可逆,拿到 5d41402abc4b2a76b9719d911017c592 也推不回原文(它是 hello 的 MD5,空字符串的是 d41d8cd98f00b204e9800998ecf8427e);雪崩效应,改一个比特,结果面目全非。

所以"MD5 加密"这个说法本身是错的,它只能回答两个问题:这两份数据是不是同一份?这份数据还是不是我拿到的那一份?想保密要靠加密,想存口令要靠带盐的慢哈希,两者都不该拿 MD5 顶替。

二、校验的关键其实是"期望值从哪来"

很多人把流程记成"下载—算哈希—比对",但决定结论价值的只有第三步里参照物的来源。分开看:

期望值来源校验通过说明什么校验失败说明什么
官网 HTTPS 页面单独公布文件与官网那份一致,没在传输中坏掉传输截断、被替换或版本拿错,重下
和文件同一个第三方下载站只能说明这两样东西配套,几乎不能说明安全连站家的说明都抄错了
GPG/代码签名,另附公钥来源可信且未被篡改,这才是防篡改签名无效,别装
自己上次备份时记录的清单这段时间里文件没变、没坏介质或写入出问题了,立刻找另一份副本

中间那一行是我觉得最该写进说明书的:攻击者替换安装包时,顺手改掉页面上的 MD5 只需要几秒。哈希保证的是"完整性",不是"真实性",后者要靠签名和渠道信任。

三、我实际怎么算,用哪些命令

系统自带的命令先记住,不依赖网络也能用:

平台命令输出
Windows(cmd)certutil -hashfile app.iso MD532 位十六进制
Windows(PowerShell)Get-FileHash -Algorithm SHA256 app.iso64 位十六进制
macOSmd5 app.iso / shasum -a 256 app.isoMD5 / SHA-256
Linux、Git Bashsha256sum app.iso;整批 sha256sum -c SHA256SUMS逐行 OK / FAILED

手边只有一两个文件、不想敲路径时,我把它们直接拖进文件 MD5 计算:批量拖入后一次得到 MD5、SHA-1、SHA-256 三种值,同时列出文件名、大小、类型和修改时间,哈希相同的会标红——上次清重复安装包就是靠这个标红挑出来的。计算用浏览器自带的接口完成,文件不上传;几十 GB 的镜像我还是用命令行更稳。

备份这边我的固定动作是三步:拷完 → 在源端生成一份 SHA256SUMS.txt → 把清单复制到另一台机器。恢复前 -c 跑一遍,两百多个包哪几个坏了直接看得到。文本类的短字符串(对接口签名的原文)我另开一页算,MD5 工具支持 16 位与 32 位、大小写切换和多行批量。

四、MD5 现在还能不能信

答案取决于对手是谁。MD5 的碰撞已经被实际构造出来,2008 年研究者利用它伪造过 CA 证书,所以对抗性场合都不该再用:软件签名、证书链、口令存储,一律换 SHA-256 起步。反过来,"我这份文件在拷贝时有没有断"这种非对抗场景它照样够用,因为坏档不是有人专门针对你的文件构造出来的。

用途合适的算法原因
下载完整性、备份自检MD5 或 SHA-256只需发现无意损坏
安装包、镜像对外公布SHA-256 + 签名MD5 可被碰撞,挡不住蓄意替换
口令存储bcrypt / scrypt / Argon2MD5 太快,加盐也救不了
接口签名、防重放HMAC-SHA256需要带密钥的认证码,哈希计算器一次出 MD5 到 SHA-512 六种结果并支持 HMAC
文件去重MD5 起步速度快;重要数据去重后再抽查一次内容

五、几个会让人白排查的坑

  • 16 位和 32 位不是两种算法:16 位只是取 32 位结果的第 9 到 24 个字符。比对前先确认长度,不然会以为"完全对不上"。
  • 大小写:a-f 与 A-F 是同一个值,只是展示格式。脚本比对前统一转小写。
  • 换行符改变文本哈希:同一份 README.md 在 Windows 下是 CRLF、Linux 下是 LF,MD5 必然不同;Git 的 core.autocrlf 也会造成同样结果。比文本哈希前先统一行尾。
  • 改名、改时间不影响哈希:指纹只算内容,所以"我改了文件名哈希应该变"的直觉是错的,也正因如此它才适合用来判断两份内容是否相同。
  • 外层包和内层文件是两回事:zip 的哈希一致只保证包没坏,包内有没有被替换要看逐文件清单。
  • 目录没有单一哈希:文件顺序、权限、时间戳都会改变打包结果。核对整个目录要用逐文件清单或 rsync 的校验模式。

六、常见疑问

Q:两个文件 MD5 相同就一定完全一样吗?

日常场景可以这么判断,随机损坏导致相同的概率低到可以忽略。只有当你面对一个会主动构造碰撞的对手时才需要升级算法。

Q:官网只给 SHA-256,我机器上只有 md5sum 怎么办?

换算法而不是换文件:PowerShell 的 Get-FileHash、macOS 的 shasum -a 256、Linux 的 sha256sum 都能直接算,不必重新下载。

Q:校验不一致该怎么处理?

先重下一次再算,仍不一致就当它被改动过:不要运行,不要用其中的文件,同时确认自己是不是拿错了版本或者从镜像站下的。

Q:备份一定要留哈希清单吗,直接定期重拷不行?

重拷不能告诉你盘里那份是不是已经坏了,只能赌。清单的成本是几十秒计算,收益是恢复前就知道哪些包可用。

Q:算大文件要多久?

主要卡在磁盘读取而不是算法,同一块盘上 SHA-256 和 MD5 的耗时差别往往小于读写速度本身。机械盘上等几分钟正常,浏览器里过大的文件还会受内存限制。

那次坏档最后没造成实质损失——同批数据在另一台机器上还有一份旧副本,只缺了两个月。真正改变的是流程:现在备份一结束我就把哈希清单写到第二份存储上,因为"有一份备份"和"知道备份是好的"是两回事。

📎 相关文章

PNG 压了三遍只减 426 字节:无损压缩的真实边界 2026-10-22 WebP 转 PNG 后体积涨了几倍:什么时候必须转,怎么把涨幅压住 2026-10-22 截图缩到四分之一,小字糊成一团的三种原因 2026-10-22 同样裁 300×300,头像为什么总偏右下角半格 2026-10-22 按每月 1.7 倍预估 18 个月,脚本和表格为什么给出两个数 2026-10-22