常用哈希算法对比:MD5、SHA-1、SHA-256、SHA-512
哈希算法是密码学的基础。本文对比常用哈希算法的特点、安全性和适用场景。
什么是哈希算法?
哈希算法是一种单向函数,将任意长度的输入转换为固定长度的输出(哈希值)。
输入: "Hello" → MD5 → "8b1a9953c4611296a827abf8c47804d7"
输入: "Hello World" → MD5 → "b10a8db164e0754105b7a99be72e3fe5"
特点
- 确定性:相同输入总是产生相同输出
- 单向性:无法从哈希值反推输入
- 抗碰撞性:难以找到两个不同的输入产生相同哈希值
- 雪崩效应:输入的微小变化导致输出巨大变化
常用哈希算法对比
| 算法 | 输出长度 | 安全性 | 速度 | 适用场景 |
|---|---|---|---|---|
| MD5 | 128位 | ❌ 已破解 | 最快 | 文件校验 |
| SHA-1 | 160位 | ❌ 已破解 | 快 | Git 提交 |
| SHA-256 | 256位 | ✅ 安全 | 中等 | 区块链、HTTPS |
| SHA-512 | 512位 | ✅ 安全 | 中等 | 高安全需求 |
| SHA-3 | 可变 | ✅ 最安全 | 较慢 | 未来标准 |
MD5(Message Digest 5)
特点
- 输出 128 位(32 个十六进制字符)
- 计算速度最快
- 已被破解,存在碰撞攻击
适用场景
- 文件完整性校验(非安全场景)
- 数据去重
- 缓存键生成
不适用场景
- 密码存储
- 数字签名
- 安全证书
// Java MD5 示例
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest("Hello".getBytes());
String hex = Hex.encodeHexString(hash);
SHA-1(Secure Hash Algorithm 1)
特点
- 输出 160 位(40 个十六进制字符)
- 2017 年被 Google 攻破
- Git 仍使用 SHA-1 标识提交
适用场景
- Git 提交标识(非安全用途)
- 旧系统兼容
不适用场景
- 新项目的安全需求
- SSL/TLS 证书
SHA-256(SHA-2 家族)
特点
- 输出 256 位(64 个十六进制字符)
- 目前广泛使用的安全哈希算法
- 比特币使用 SHA-256 挖矿
适用场景
- 密码存储(加盐后)
- 数字签名
- 区块链
- HTTPS 证书
// Java SHA-256 示例
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("Hello".getBytes());
String hex = Hex.encodeHexString(hash);
SHA-512
特点
- 输出 512 位(128 个十六进制字符)
- 64 位系统上比 SHA-256 更快
- 安全性与 SHA-256 相当
适用场景
- 高安全需求
- 64 位系统优化
SHA-3
特点
- 2015 年成为标准
- 与 SHA-2 完全不同的设计
- 抗量子计算攻击
适用场景
- 未来安全需求
- 高安全性场景
密码存储最佳实践
❌ 错误做法
// 明文存储
String password = "123456";
// 简单 MD5
String hash = MD5(password);
// MD5 + 固定盐
String hash = MD5(password + "salt");
✅ 正确做法
// 使用 bcrypt
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String hash = encoder.encode(password);
// 验证
boolean matches = encoder.matches(password, hash);
推荐算法
| 算法 | 推荐度 | 说明 |
|---|---|---|
| bcrypt | ⭐⭐⭐⭐⭐ | 最常用,自适应成本 |
| scrypt | ⭐⭐⭐⭐ | 内存密集型 |
| Argon2 | ⭐⭐⭐⭐⭐ | 最新标准,推荐新项目 |
在线工具
使用 jsjson.com MD5 工具 和 SHA-256 工具 进行哈希计算。
总结
选择哈希算法时,需要考虑安全性和性能的平衡。对于密码存储,使用 bcrypt 或 Argon2;对于数据校验,SHA-256 是目前的最佳选择。