← 返回博客首页

文本哈希工具怎么选:MD5、SHA 系列与 BCrypt 的边界

哈希到底是什么?

哈希(Hash)是把任意长度的输入通过单向函数映射成固定长度输出(摘要)的过程。一个好的密码学哈希具备四个性质:

性质 含义 为什么重要
确定性 同输入永远同输出 校验可复现的前提
雪崩效应 改 1 个比特,输出约一半比特翻转 无法从摘要相似度推断输入相似度
抗原像 给摘要反推输入在计算上不可行 单向性的核心
抗碰撞 难找到两个不同输入产出同一摘要 防伪造的基石

雪崩效应直观感受一下(SHA-256):

输入: hello          输出: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
输入: hellp          输出: 4ef1a2c9d5e7f0b3a8c6d1e4f7a0b3c6d9e2f5a8b1c4d7e0f3a6b9c2d5e8f1a4

只改了一个字母,64 个十六进制字符完全不同。这正是「不能用哈希值比较来判断两段内容是否相近」的原因——哈希不保留任何相似性信息。

但「单向」不等于「不可破解」:对短密码或常见字符串,攻击者可以用彩虹表或暴力穷举反查。所以哈希的用途必须选对。

四大用途,四种选法

用途 推荐 原因
文件完整性校验 MD5 / SHA-256 快、可复现,目的是检测传输损坏而非防攻击
数据指纹 / 去重 SHA-256 碰撞概率极低,输出稳定
防篡改签名 HMAC-SHA256 必须有密钥参与,且不能用字符串拼接
密码存储 BCrypt / Argon2 慢哈希 + 盐,专为抵抗暴力破解设计

需要随时对照各算法输出长度与当前安全状态,可开一份 哈希算法速查表

输出长度与碰撞概率:生日攻击

一个常被误解的点:n 位哈希的抗碰撞强度不是 2ⁿ,而是 2^(n/2)。原因是「生日悖论」——不需要找到特定输入的碰撞,只要任意两个输入撞上即可,所需尝试次数约为 2^(n/2)。

算法 输出位 抗碰撞强度 状态
MD5 128 2⁶⁴(已被实际攻破) ❌ 禁用于安全场景
SHA-1 160 2⁸⁰(已被实际攻破) ❌ 禁用于安全场景
SHA-256 256 2¹²⁸ ✅ 安全
SHA-512 512 2²⁵⁶ ✅ 安全

2⁶⁴ 听起来很大,但在专用硬件上已经可达——这正是 MD5/SHA-1 被淘汰的原因:不是理论缺陷,而是已经出现了可复现的碰撞构造(如 SHAttered 攻击用 SHA-1 造出两份内容不同但摘要相同的 PDF)。

MD5 / SHA-1:已不安全但仍有用武之地

MD5(128 位)和 SHA-1(160 位)已被证明存在实际碰撞攻击,绝不能用于安全标识、数字签名、证书。但在「文件去重」「缓存键」「非安全校验和」这类不防敌手的场景,它们依然快且可用。

经验法则:如果攻击者有可能精心构造输入来骗你,就别用 MD5/SHA-1。否则(如本地文件比对)可以用。

SHA-2 家族:当前默认安全选择

SHA-256 / SHA-384 / SHA-512 同属 SHA-2,目前无已知实用碰撞攻击,是绝大多数安全场景的默认选择:

  • SHA-256:输出 256 位,最通用,区块链、证书、Git 提交、文件签名都用它。
  • SHA-512:输出 512 位,在 64 位 CPU 上更快,抗长度扩展攻击表现更好。

一个必须知道的坑:长度扩展攻击

SHA-2 用的是 Merkle–Damgård 构造,它有个反直觉的性质:知道 H(secret || msg)len(msg),就能在不知道 secret 的情况下算出 H(secret || msg || padding || 追加内容)

这意味着下面这种「自制签名」是可以直接被伪造的:

// ❌ 危险:可被长度扩展攻击伪造
const sig = sha256(SECRET + body);

// ✅ 正确:HMAC,结构上免疫
const sig = hmacSha256(SECRET, body);

这在 Webhook 验签、API 签名里是最常见的严重漏洞之一。生成与验证 HMAC 可以直接用 HMAC 生成工具

为什么密码不能用 SHA?

SHA 的设计目标是——这是它的优点,却是密码存储的致命缺点。攻击者用一张 GPU 每秒可算数十亿次 SHA,弱密码瞬间被破。

密码存储需要慢哈希(slow hash)+ 盐(salt)

方案 特点 关键参数
BCrypt 自适应成本因子,自动加盐 cost ≥ 12(每 +1 耗时翻倍)
Argon2id 2015 密码哈希竞赛冠军,内存硬 内存 ≥ 19 MB、迭代 ≥ 2、并行度 1–4
SCrypt 内存硬,抗硬件加速 N ≥ 2¹⁴、r = 8、p = 1
PBKDF2 兼容性最好,但非内存硬 迭代 ≥ 600,000(OWASP 2023)

内存硬(memory-hard)是关键:GPU 的核心多但每核心内存小,Argon2/SCrypt 通过强制占用大量内存,直接把 GPU 的并行优势废掉一半。

本站 hash-text通用单向哈希工具,适合校验/指纹/签名验真;密码存储请用 Bcrypt 哈希工具 这类专门方案,不要在这里「哈希一下密码就存库」。完整的算法对比与参数取舍见 密码哈希指南

哈希 ≠ 加密

加密(AES 等) 哈希(SHA/MD5/BCrypt)
可逆性 ✅ 有密钥可还原 ❌ 单向
输出长度 与明文相关 固定
用途 保护机密 验证完整性 / 生成指纹
典型误用 把哈希当加密,指望能解密

需要把数据还原出来?用加密,不是哈希。

文件校验实操

下载大文件后核对摘要,是哈希最日常的用法:

# Linux / macOS
sha256sum ubuntu-24.04.iso
# 与官网给出的摘要逐字符比对

# Windows PowerShell
Get-FileHash .\ubuntu-24.04.iso -Algorithm SHA256

# Windows cmd
certutil -hashfile ubuntu-24.04.iso SHA256

要点:比对的必须是官网通过 HTTPS 公布的摘要,而不是下载页面旁任意一个镜像站贴的值。想快速验证一小段文本,也可以直接用 文本哈希工具(本地计算,不上传)。

常见误用清单

误用 后果 正确做法
用 MD5 做防篡改 可被构造碰撞 SHA-256,且需密钥时用 HMAC
hash(secret + msg) 当签名 长度扩展攻击可伪造 HMAC-SHA256
用裸 SHA 存密码 GPU 秒破 BCrypt / Argon2id
把哈希当加密 数据无法还原 AES
用哈希做随机源 输出可预测 CSPRNG(crypto.randomBytes
依赖哈希「隐藏」数据 短明文可被彩虹表反查 加盐,或改用加密

选型决策树

需要哈希?
├── 要能还原原始数据?
│   └── ❌ 哈希做不到,改用 AES 加密
├── 要验证内容没被改?
│   ├── 有共享密钥? → HMAC-SHA256
│   └── 无密钥、只验完整性? → SHA-256(非安全场景可用 MD5)
├── 要生成指纹 / 去重 / 缓存键?
│   └── SHA-256(追求极致速度且无对手 → BLAKE3)
├── 要存密码?
│   └── Argon2id 优先,其次 BCrypt(cost≥12),绝不用 SHA/MD5
└── 要签名?
    └── 用成熟的签名算法(Ed25519 / RS256),不要自己拼哈希

常见问题

MD5 还能用吗?

用于「完整性校验 / 非安全场景」(如文件去重、缓存键)仍可用,因为它快且无碰撞攻击风险影响这些用途。但任何涉及「防篡改 / 防伪 / 安全标识」的场景都不要用 MD5/SHA-1,改用 SHA-256。

SHA-256 和 SHA-512 怎么选?

两者都安全。SHA-256 输出 256 位,在 32 位/移动端和高并发校验中更省;SHA-512 输出 512 位,64 位平台上更快且抗长度扩展攻击略好。普通场景选 SHA-256 即可。

为什么密码不能用 SHA 存储?

SHA 系列设计目标是「快」,攻击者可用 GPU 每秒算数十亿次。密码存储需要「慢哈希」+ 盐(salt),如 BCrypt/Argon2/SCrypt,故意拖慢单次计算以抵抗暴力破解。本站 hash-text 工具是通用哈希,不是密码存储方案。

哈希和加密是一回事吗?

不是。加密可逆(有密钥可还原明文),哈希单向(理论上不可还原)。哈希用于「验证完整性 / 生成指纹」,加密用于「保护机密」。需要还原数据请用 AES(本站 AES 加密工具)。

加盐(salt)是什么?

salt 是在哈希前拼接到原文的随机值,使相同明文产生不同哈希,阻止彩虹表批量反查。通用哈希工具通常不自动加盐(因为要可复现),密码存储的 salt 由 BCrypt 等专业方案自动处理。

为什么不能直接用 `hash(密钥 + 消息)` 做签名?

**因为 SHA-256 这类 Merkle–Damgård 构造存在长度扩展攻击。** 攻击者拿到 `H(secret || message)` 和 `message` 的长度后,即使不知道 `secret`,也能构造出 `H(secret || message || padding || 附加内容)` 的有效哈希——他可以在消息尾部追加内容并给出合法签名。正确做法是用 **HMAC**(`HMAC-SHA256`),它通过两重嵌套哈希把密钥混入初始状态,结构上免疫该攻击;或者直接用 **SHA-3 / BLAKE3**(采用海绵构造,无此问题)。**永远自己拼字符串当签名,是 Webhook 验签里最常见的严重漏洞之一。**

← 返回博客首页