安全 · 哈希

MD5、SHA-1、SHA-256:到 2026 年了,到底该用哪个

网上 90% 的哈希对比文章告诉你"SHA-256 比 MD5 更安全"——这是废话。真正的问题是:你要解决什么。给文件算指纹和给密码加盐用的根本不是同一类东西。这篇按场景倒推该用哪个。

先看场景表

不想看推理过程?直接对号入座:

你要干什么用什么原因
存用户密码bcrypt / Argon2SHA-256 都不行——见下文
文件下载校验SHA-256抗碰撞 + 广泛工具支持
API 请求签名(HMAC)HS256 / HS512HMAC 的 H 就是 hash,外加 secret
缓存键 / 数据去重MD5 也行不需要安全性,要的是快
Git 内部对象SHA-1(在迁 SHA-256)历史包袱,自己写代码别用
区块链 / 加密货币SHA-256 / Keccak-256抗 collision 关键
JWT 签名HS256 / RS256HMAC 或非对称
🚫

密码存储SHA-256(password + salt) 是常见错误。SHA-256 设计目标是,但密码哈希要的是——慢到攻击者暴力破解算不起。bcrypt / Argon2 的 cost factor 让你能调节这个慢度。

什么是哈希——一句话

把任意长度的输入压成固定长度的"指纹"。两个不同输入得到相同输出叫"碰撞",理论上不可避免(鸽笼原理),但好的哈希算法让构造碰撞变得实际上不可行

四个核心属性:

不同算法的差异主要在第 4 点上。

MD5:2026 年还能用,但要小心

1992 年发布,128 位(32 个 hex 字符)。

echo -n "hello" | md5sum
# 5d41402abc4b2a76b9719d911017c592  -

现状:2004 年王小云团队公布碰撞攻击,2008 年实战级 collision 出现。现在用 GPU 几秒就能构造两个 MD5 相同的不同文件。

但 MD5 没死透——以下场景仍合理:

规则:只要不是对手能控制输入的场景,MD5 还能凑活用。

SHA-1:基本上别用

1995 年发布,160 位。Git 现在还在用——但 Git 也在迁。

echo -n "hello" | sha1sum
# aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d  -

2017 年 Google 公布 SHAttered 攻击,用 9.2 万亿亿次哈希计算找到了第一个 SHA-1 碰撞。当时算力还很贵;2026 年的今天,AWS 上跑一周就能搞出来。

Git 2.43+ 已经支持 SHA-256 作为对象哈希,但生态还在迁移中。如果你自己写代码:跳过 SHA-1,直接 SHA-256

SHA-256:现在的默认

2001 年作为 SHA-2 家族成员发布。256 位。在可预见的将来(至少十年)安全性没问题。

echo -n "hello" | sha256sum
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824  -

什么时候用 SHA-512 而不是 SHA-256?64 位机器上 SHA-512 在某些场景更快(因为 64 位字操作更适合 64 位 CPU)。但输出长度翻倍带来传输/存储开销。一般默认 SHA-256。

密码存储为什么不用 SHA-256

这是新人最常错的地方。看到 SHA-256 标"安全",就拿来存密码:

// ❌ 错误示范
const hash = sha256(password + salt);
// 现代 GPU 每秒能算 100 亿次 SHA-256
// 8 位密码空间 ~10 万亿,几小时就能爆破

正确做法用为密码场景设计的算法:

// ✅ Node.js / bcrypt
import bcrypt from "bcrypt";
const hash = await bcrypt.hash(password, 12);  // cost=12 大约 0.5 秒/次
// 攻击者爆破 1 个密码要算几小时,整库爆破不可行

// ✅ 更现代的选择:Argon2 (2015 PHC 比赛冠军)
import argon2 from "argon2";
const hash = await argon2.hash(password);

关键区别:cost factor。bcrypt cost=12 比 cost=10 慢 4 倍;硬件升级了你就 cost+=1,让攻击者也得跟着付出更多算力。SHA-256 没有这个参数。

⚠️

"我们公司还在用 MD5 存密码"——这不是末日,但确实是技术债。迁移方案:用户下次登录时校验旧 MD5 通过后,重新用 bcrypt 哈希存进库,旧 MD5 字段清空。逐步替换,不影响存量用户。

各语言怎么算

JavaScript (浏览器)

async function sha256(text) {
  const buf = new TextEncoder().encode(text);
  const hash = await crypto.subtle.digest("SHA-256", buf);
  return Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2, "0"))
    .join("");
}
await sha256("hello");
// "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

Python

import hashlib
hashlib.sha256(b"hello").hexdigest()
# '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'

命令行

# macOS / Linux
echo -n "hello" | sha256sum

# openssl 各平台都有
openssl dgst -sha256 file.txt

# 看大文件别 cat | sha256sum(多一次复制),直接:
sha256sum bigfile.iso
💡

需要在浏览器里算文件/文本哈希,直接用 在线哈希生成器,所有算法本地计算不上传。HMAC 签名场景去看 JWT 编辑器

关于"算力涨了所以哈希都会被破"

常见的误解。哈希算法不是简单的"更长更安全"。SHA-256 的安全性建立在找碰撞需要尝试 2128这个数学难度上。摩尔定律就算继续 50 年,也不到这个数量级。

真正的威胁是数学突破——比如 SHA-1 被破是因为有人找到了构造碰撞的捷径。SHA-256 至今没有被发现这种捷径。但万一明天有人发现了——届时再换 SHA-3 或量子抗性算法。对工程来说,今天用 SHA-256 是对的决定

在线哈希工具

MD5 / SHA-1 / SHA-256 / SHA-512,文本和文件都支持,全本地计算

打开哈希生成器