核心答案:哈希是把任意长度数据映射为定长指纹的单向函数——MD5 出 32 位十六进制、SHA-256 出 64 位。MD5/SHA-1 已被破解只能用于校验文件完整性;存密码必须用 bcrypt/scrypt/Argon2 这类慢哈希加盐。
哈希基础
哈希函数三大特性:
- 单向性:从哈希值无法反推原文
- 雪崩效应:输入改 1 位,输出天翻地覆
- 定长输出:1 字节和 1 GB 文件哈希值一样长
"hello" 的 SHA-256:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
常见算法对照表
| 算法 | 输出长度 | 状态 | 可用场景 |
|---|---|---|---|
| MD5 | 128 位/32 hex | ❌ 已破解 | 仅文件完整性校验 |
| SHA-1 | 160 位/40 hex | ❌ 已破解(2017 谷歌碰撞) | 同上,逐步淘汰 |
| SHA-256 | 256 位/64 hex | ✅ 安全 | 签名、区块链、校验 |
| SHA-512 | 512 位 | ✅ 安全 | 高安全场景 |
| bcrypt | 60 字符 | ✅ 密码专用 | 密码存储 |
| Argon2 | 可变 | ✅ 密码专用(2015 竞赛冠军) | 密码存储首选 |
典型用途
| 场景 | 用法 |
|---|---|
| 文件校验 | 下载页给出 SHA-256,本地算一遍比对 |
| 密码存储 | bcrypt(密码+随机盐) 存库 |
| 数据指纹 | Git 用 SHA-1 标识每次提交 |
| 数字签名 | 先哈希再私钥加密 |
| 区块链 | 区块头哈希串联成链 |
MD5 为什么不安全
- 2004 年王小云团队实现理论碰撞,2012 年 Flame 病毒利用 MD5 碰撞伪造微软签名
- 现代 GPU 每秒可算数百亿次 MD5,彩虹表全覆盖常见密码
- "碰撞"意味着两个不同文件可以有相同 MD5——校验防篡改已不可信
- 现状定位:只能用于"非恶意场景"的完整性检查(如传输误码)
密码存储正确姿势
| 做法 | 评级 |
|---|---|
| 明文存储 | 灾难 |
| MD5(密码) | 灾难(彩虹表秒破) |
| SHA-256(密码) | 差(太快,GPU 暴力破解友好) |
| SHA-256(密码+盐) | 一般(仍太快) |
| bcrypt(密码+盐, cost≥10) | 好 |
| Argon2id(密码+盐) | 最佳 |
慢哈希的核心:故意让单次计算耗时 100ms+,攻击者每秒只能试 10 个密码。
常见误区
- 哈希=加密:加密可逆(有密钥能解密),哈希不可逆。说"MD5 加密"是术语错误。
- 哈希后再 Base64 就安全:编码不改变安全性,攻击者解码后再破哈希。
- 自己发明哈希算法:密码学第一铁律——不要自造轮子,用经公开审查的标准算法。
- 盐可以复用:每个密码必须用独立随机盐,否则彩虹表依然有效。
用[哈希计算器](/c/dev/hash)在线计算文本的 MD5/SHA-1/SHA-256。