📝 博客 · 2026-07-29 · ⏱ 9 分钟

什么是MD5哈希?和SHA256有什么区别?

讲清楚哈希是什么、MD5 和 SHA256 的原理与区别、为什么 MD5 不再安全,以及加盐的作用。

一、哈希是什么

哈希(Hash)是一种把任意长度的数据映射成固定长度摘要的算法。它有几个关键特征:

  1. 单向:只能从原文算出哈希值,不能从哈希值反推原文。
  2. 固定长度:无论输入 1 个字节还是 1GB,输出长度都一样。
  3. 确定性:同一算法、同一输入,每次算出的结果都一样。
  4. 雪崩效应:输入改一个字符,输出会面目全非。
  5. 抗碰撞:很难找到两个不同的输入产生相同的输出。

举个例子,字符串 "hello" 的几个常见哈希值:

MD5:     5d41402abc4b2a76b9719d911017c592
SHA256:  2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

只改一个字符,把 "hello" 改成 "Hello"(大写 H):

MD5:     8b1a9953c4611296a827abf8c47804d7
SHA256:  185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969

可以看到输出完全变了,这就是雪崩效应。

二、MD5 的历史

MD5 由麻省理工学院的 Ronald Rivest 在 1992 年设计。Rivest 是 RSA 加密算法的"R"(另外两位是 Adi Shamir 和 Leonard Adleman,三人因此获得 2002 年图灵奖)。

MD5 的全称是 Message Digest Algorithm 5,是 MD4 的改进版本。它的输出长度固定为 128 位(16 字节),通常用 32 个十六进制字符表示。

设计之初,MD5 的目标是:

在 1990 年代到 2000 年代初,MD5 几乎是互联网上最流行的哈希算法。

三、SHA256 是什么

SHA256 属于 SHA-2 家族(Secure Hash Algorithm 2),由美国国家安全局(NSA)设计、美国国家标准与技术研究院(NIST)在 2001 年发布。它的输出长度是 256 位(32 字节),通常用 64 个十六进制字符表示。

SHA-2 家族还包括 SHA224、SHA384、SHA512 等变体,区别主要是输出长度和内部循环次数。目前 SHA256 是使用最广泛的一个,被用于:

四、MD5 vs SHA256 对比

维度MD5SHA256
输出长度128 位256 位
字符长度32 位十六进制64 位十六进制
计算速度较慢(约 MD5 的 1/2 到 1/3)
安全性已被破解,不推荐安全,目前无有效攻击
碰撞难度已能人为构造碰撞暂无实际碰撞攻击
标准化RFC 1321FIPS 180-4
典型场景文件校验(非安全场景)证书、区块链、密码存储
设计者Ronald RivestNSA / NIST

从速度上看 MD5 确实更快,但在现代 CPU 上 SHA256 的性能也已经足够好。大多数场景下,速度差异可以忽略。

五、MD5 为什么不再安全

MD5 的"破解"并不是说能从哈希值反推出原文——哈希算法本身是数学上不可逆的。MD5 的安全问题在于碰撞(Collision):找到了一种方法,能人为构造出两个不同的输入,使它们产生相同的 MD5 值。

时间线:

年份事件
1996Rivest 自己发现 MD5 存在理论弱点
2004中国密码学家王小云团队公布 MD5 碰撞的快速构造方法
2008研究者用 MD5 碰撞伪造了 CA 证书,整个互联网震惊
2012Flame 病毒利用 MD5 碰撞伪造微软证书
至今主流浏览器、CA 机构全面弃用 MD5

碰撞攻击的实际危害在于:攻击者可以构造一个看似合法、实际是恶意的文件,让它和合法文件有相同的 MD5。如果系统只校验 MD5,就会把恶意文件当成合法文件放行。

所以现在如果你在系统里用 MD5 做安全校验,等于没做。

六、彩虹表攻击

即使算法本身没被破解,简单的哈希也不适合存密码。因为哈希的"确定性"意味着:相同的密码永远产生相同的哈希值

攻击者可以提前算好一张"密码 → 哈希"对照表,比如:

密码MD5
123456e10adc3949ba59abbe56e057f20f883e
password5f4dcc3b5aa765d61d8327deb882cf99
admin21232f297a57a5a743894a0e4a801fc3

这就是彩虹表(Rainbow Table)。它体积可以做到几个 TB,覆盖几乎所有常见密码。一旦数据库泄露,攻击者拿着哈希值往表里一查,几秒就能还原出明文密码。

应对彩虹表的方法是加盐(Salt):在密码前后加一段随机字符串再哈希。

import hashlib, secrets

# 错误做法
hash = hashlib.md5("password123".encode()).hexdigest()

# 正确做法(概念示意,实际要用 PBKDF2/bcrypt/scrypt)
salt = secrets.token_hex(16)
hash = hashlib.pbkdf2_hmac("sha256", "password123".encode(), salt.encode(), 100000)

加盐之后,即使两个用户用了同样的密码 123456,因为盐不同,存储的哈希值也完全不同,彩虹表就失效了。

七、密码存储的正确姿势

存密码不能用 MD5 或 SHA256 直接哈希一次,原因有两个:

  1. 现代 GPU 每秒能算几亿次 SHA256,暴力破解弱密码依然很快
  2. 通用哈希算法设计目标是快,而不是抗暴力破解

正确的做法是用专门的密码哈希函数

算法特点
bcrypt自带盐、可调工作因子,最广泛使用
scrypt内存困难型,抗 GPU/ASIC 攻击
Argon22015 年密码哈希竞赛冠军,目前最推荐
PBKDF2标准化、兼容性好,但安全性弱于前三个

这些算法的共同点是:可以配置计算开销,让单次哈希耗时 100ms 左右。正常用户登录时多等 100ms 没感觉,但攻击者暴力破解时要算几亿次,成本直接高到不可行。

八、什么时候还能用 MD5

虽然 MD5 不再适合安全场景,但在一些非安全场景下仍然有用:

场景说明
文件完整性校验下载完文件算一次 MD5 对比,防止下载损坏
缓存键用 MD5 把长 URL 变短,作为缓存 key
去重对内容做 MD5,相同内容会产生相同哈希
分库分表用 MD5 取模把数据均匀分到不同表

这些场景不依赖抗碰撞性,只要哈希分布均匀、计算够快就行。

九、实践推荐

日常开发中经常需要算一段文本或一个文件的哈希值——校验文件完整性、对比数据、生成缓存键等等。在线工具最方便:

支持 MD5、SHA1、SHA256、SHA512 等多种算法,可以输入文本或上传文件,实时显示结果,是开发调试和文件校验时的常用工具。