杂记 › 技术笔记 › MD5不安全了?改用SHA-256给文件和数据上个"指纹锁"

MD5不安全了?改用SHA-256给文件和数据上个"指纹锁"

我们一度用 MD5 做安装包校验。有天同事说"哈希对不上,这个包有问题",于是整个团队把 CDN 翻了一遍,最后原因是他下载的其实是 CDN 返回的 404 页面——一个只有几百字节的 HTML,哈希当然完全不同。另一次更麻烦:老系统把用户密码直接存 MD5,被拖库后不到两天就有人用现成的碰撞表还原出弱口令。这两件事让我把"哈希用来做什么"和"该用哪种算法"分得很清楚:校验传输有没有坏,和防止别人伪造内容,是完全不同的两个要求。

一、哈希的三个性质,决定了它只能做这三类事

  • 定长:不管输入 3 个字节还是 3 个 GB,SHA-256 输出永远是 256 位,也就是 64 个十六进制字符。
  • 单向:从摘要推不回原文。这和加密有本质区别——加密是可逆的,有密钥能还原,目的是保密;哈希的目的是"指纹"。
  • 雪崩效应:原文改 1 个字符,摘要会有大约一半的位发生变化。空字符串的 MD5 是 d41d8cd98f00b204e9800998ecf8427e、SHA-256 是 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,而末尾只多加一个空格,出来的就是两串毫不相干的值。这两个固定值还能当自检用:算出来对不上,说明工具或输入环节有问题。

因此它能可靠回答三个问题:这两份内容是否一致;这份内容是否被改动过;以及在不暴露原文的前提下能否证明我知道原文。它不能回答的问题是"这段密文是什么"。

二、MD5 不安全到什么程度,还剩下什么用

算法输出十六进制长度现状适合的用途
MD5128 位32 字符碰撞可在普通硬件上构造,签名证书领域已宣告失效非对抗场景的完整性校验、数据去重分桶
SHA-1160 位40 字符同样存在实际碰撞,主流浏览器与证书体系已淘汰兼容旧系统的校验值
SHA-256256 位64 字符当前推荐,广泛用于签名、区块摘要、制品校验安全场景默认选择
SHA-512512 位128 字符强度更高,摘要更长、传输与人工核对成本上升高强度要求、需要更长摘要时

"碰撞"指有人刻意构造出两个内容不同、摘要却相同的输入。一旦可被制造,"摘要相同即内容可信"这个前提就被破坏——这才是 MD5 被赶出安全场景的原因。但反过来看,下载中断、CDN 回源错误、文件被脚本误改,这些都不是有人在构造碰撞,MD5 依然够用。真正的分歧点只有一个:有没有对手会主动构造第二份内容。

三、口令存储是第三件事,别混进来

把 MD5 或 SHA-256 拿来存密码,是同一系列里最贵的误用。快的哈希恰恰是攻击者的朋友:一块消费级显卡每秒能试算海量候选,撞库脚本配上现成的彩虹表,常见弱口令几乎瞬间还原。正确做法是用带盐的慢哈希——bcrypt、scrypt、Argon2id 这类自带盐值并可调工作因子的算法,让每次验证都要付出可控的计算成本。盐的作用是相同密码得到不同摘要,从而废掉批量预计算;它不是密钥,可以明文存储。

四、我的实际流程

  1. 拿到校验值先确认算法名与格式。很多"对不上"来自 16 位与 32 位混用:所谓 16 位 MD5 只是取 32 位结果的第 9 到第 24 个字符,天生就"对不上"完整值;同理还有大小写显示差异,a–f 与 A–F 表达的是同一个摘要。
  2. 文本类要在同一个工具里一次算完再比。我的习惯是把待校验内容贴进哈希计算器,MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512 六种摘要一次列出来,逐行和对方公布的值对照,需要哪一行就单独复制哪一行。很多历史系统只给 MD5,而新规范要求 SHA-256,一次全出就不用反复换工具重算第二遍;比对时顺手把大小写统一,能省掉一半"看着不一样"的误判。
  3. 文件走文件校验。安装包这类几百 MB 的东西用文件 MD5 计算,可以一次拖进多个文件同时得到 MD5、SHA-1、SHA-256,比对是否下错包时很直观。
  4. 接口签名用 HMAC,不用裸哈希拼密钥。md5(secret + params) 这种写法有过被绕过的记录(涉及长度扩展等构造方式),改用 HMAC-SHA256 就把密钥的参与方式交给一个专门设计过的结构。在同一个计算器里填密钥即可得到 HMAC 值,用来核对客户端签名。

五、常见疑问

Q:哈希和加密到底有什么区别?

哈希单向、定长、不需要密钥,用于校验与指纹;加密可逆、需要密钥,用于保密传输与存储。要还原内容就只能用加密,不能指望"解哈希"。

Q:SHA-256 能反推出原文吗?

不能。只能靠穷举候选再比对摘要,所以原文本身的随机度决定安全性——口令太短,换 SHA-256 也一样被撞出来。

Q:文件校验值对不上,先怀疑什么?

先怀疑"比的不是同一个东西":下载到了错误页或被截断、文本换行符被改(CRLF 与 LF 会让纯文本摘要完全不同)、编码从 UTF-8 变成 GBK、以及 16 位对 32 位。把文件大小和行数先看一眼,能排除八成的误报。

Q:能不能自己发明一种哈希方案?

不建议。安全强度来自公开算法经过多年攻击验证,而不是把几个摘要串起来或自定义排序这类组合,后者往往引入了新的可构造点。选 SHA-256 或 SHA-512,加 HMAC,再用成熟的口令哈希算法,覆盖绝大多数需求。

Q:数据去重、找重复文件也要用 SHA-256 吗?

不涉及对手时用 MD5 更快也更省事,只需要"两份内容是否相同"。真正要防篡改的地方才需要升级到 SHA-256,这时也要一并考虑摘要本身的分发渠道是否可信。

那两次事故给我的结论很朴素:先说清楚这次比对是为了"防传输出错"还是"防人为伪造",算法的选择自己就会定下来;而"对不上"的时候,第一动作应该是确认两边算的是不是同一段字节,而不是先怀疑算法被攻破。

📎 相关文章

大小写、驼峰、下划线命名混乱?批量互转的方法 2026-10-15 这个IP是哪里的?归属地和运营商怎么查、能查到什么 2026-10-15 压缩成一行的JS看不懂?在线美化、格式化代码 2026-10-15 \u4e2d是什么鬼?中文与Unicode编码在线互转 2026-10-15 二进制、十六进制总是算不对?2/8/10/16进制互转方法 2026-10-15