PHP 密码加密方案对比:MD5、SHA、bcrypt

```html PHP 密码加密方案对比:MD5、SHA、bcrypt

PHP 密码加密方案对比:MD5、SHA、bcrypt

在用户认证系统中,**密码绝不能以明文存储**。选择安全的哈希方案至关重要。本文对比三种常见方案:已淘汰的 MD5SHA-1/SHA-256,以及现代推荐的 bcrypt

❌ MD5:完全不适用于密码(已弃用)

MD5 是快速但极度脆弱的哈希算法。其碰撞漏洞和彩虹表攻击使其在 2004 年起就不再被接受用于密码保护。

警告:PHP 8.0+ 已废弃 md5()$raw_output 参数;更重要的是——永远不要用 MD5 存储密码
// ❌ 危险示例(仅作对比,切勿使用!)
$password = "secret123";
$hash = md5($password); // e.g., "a4d2e6a3f1b8c9d0e7f6a5b4c3d2e1f0"
// 无盐、无迭代、易被暴力破解

⚠️ SHA 系列(如 SHA-256):比 MD5 强,但仍不推荐

SHA-256 等算法抗碰撞性强,但仍是**快速哈希**——攻击者可每秒尝试数十亿次(GPU/ASIC 加速)。若未加盐(salt),仍易受预计算攻击。

// ⚠️ 不推荐:手动加盐 + SHA-256(易出错且不够慢)
$salt = bin2hex(random_bytes(16));
$hash = hash('sha256', $salt . $password);
// 存储 $salt.$hash —— 但缺少自适应迭代,安全性远低于 bcrypt

✅ bcrypt:PHP 官方推荐的密码哈希方案

password_hash()password_verify() 是 PHP 内置的 bcrypt 封装,具备:自动加盐、可调强度(cost)、抗 GPU 暴力、未来兼容升级机制。自 PHP 5.5 起原生支持,是当前黄金标准。

✅ 最佳实践代码:
// ✅ 安全哈希(PHP 5.5+)
$password = "user@Passw0rd!";

// 生成哈希(自动加盐,cost=12 默认)
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// 输出示例:"$2y$12$abc123...xyz..."

// 验证密码(自动提取 salt & cost)
if (password_verify($password, $hash)) {
    echo "验证成功!";
}

// 检查是否需重新哈希(如 cost 升级或算法演进)
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
    $newHash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 14]);
}

总结与建议

  • 绝对避免:MD5、SHA-1、未加盐的 SHA-256/512;
  • 谨慎使用:PBKDF2(hash_pbkdf2)可作为 bcrypt 备选,但配置更复杂;
  • 首选方案:始终使用 password_hash() + password_verify()
  • 额外加固:结合速率限制、双因素认证(2FA)与安全传输(HTTPS)。

密码安全不是“够用就行”,而是“必须足够难破”。从今天起,请用 PASSWORD_BCRYPT —— 让攻击者的字典在你的服务器前慢下来。

```