PHP 密码加密方案对比:MD5、SHA、bcrypt
在用户认证系统中,密码安全是第一道防线。选择合适的加密方案至关重要——它不是“是否加密”,而是“如何科学地哈希”。本文对比三种常见方案:MD5、SHA 系列(如 SHA-256)与现代推荐方案 password_hash()(基于 bcrypt)。
❌ MD5:已淘汰,绝不用于密码
MD5 是快速但不安全的哈希算法,易受彩虹表攻击和碰撞攻击。PHP 中虽仍支持,但禁止用于密码存储:
// ❌ 危险示例(仅作对比,切勿使用!)
$password = "myPass123";
$md5_hash = md5($password); // e.g., "a1d0c6e83f027327d8461063f4ac58a6"
⚠️ 警告:MD5 无盐值、无迭代、计算极快,GPU 每秒可尝试数十亿次破解。PHP 官方文档明确标注其不适用于密码哈希。
❌ 原生 SHA:比 MD5 稍强,但仍不安全
SHA-256 或 SHA-512 虽抗碰撞能力更强,但仍是快速哈希。若未加盐或盐值固定,仍易被暴力/字典攻击:
// ❌ 不推荐:手动加盐且无自适应迭代
$salt = "random123"; // 静态盐值风险高
$sha_hash = hash('sha256', $salt . $password);
问题在于:盐值硬编码、无成本因子控制、无法抵御专用硬件暴力破解。
✅ bcrypt:PHP 官方推荐的现代方案
PHP 5.5+ 内置 password_hash() 和 password_verify(),底层默认使用 bcrypt(兼容 Argon2)。它具备:自动生成随机盐值、可调计算成本(默认 cost=10)、抗 GPU/ASIC 攻击。
// ✅ 推荐:一行代码完成安全哈希
$password = "myPass123";
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// 输出示例:"$2y$12$X9Z...(含盐值与参数,长度固定)"
// 验证时无需关心盐值或算法细节
if (password_verify($password, $hash)) {
echo "登录成功!";
}
✅ 优势总结:
- 盐值自动嵌入哈希字符串,永不重复
- 通过
cost参数调节计算强度(值每+1,耗时×2) - 未来可无缝升级至 Argon2(
PASSWORD_ARGON2I) - 验证函数自动解析参数,向后兼容性强
结语
永远不要自己实现密码哈希逻辑。优先使用 PHP 原生 password_hash() —— 它经过严格审计,持续更新,并屏蔽了所有底层复杂性。MD5 和裸 SHA 已属于历史遗迹;真正的安全始于选择正确的工具。
记住一句口诀:「Hash with salt, verify with ease — use password_hash, not md5.」