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., "a8b3c7d9..."
// 无盐、无迭代、易被秒破

⚠️ SHA 系列:比 MD5 强,但仍不推荐用于密码

sha1() 同样存在碰撞风险;sha256()hash('sha256', ...) 虽更安全,但仍是快速哈希——攻击者可用 GPU 每秒尝试数十亿次。若未加盐且无迭代,依然危险。

// ⚠️ 不推荐(缺乏慢哈希与自适应成本)
$hash = hash('sha256', $password . 'static_salt'); // 静态盐无效!
// ✅ 正确做法需动态盐 + 多轮迭代(但 PHP 原生不直接支持)

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

PHP 自 5.5 起内置 password_hash()password_verify(),底层默认使用 bcrypt(兼容性好、抗暴力、自动加盐、可调成本因子)。

✅ 最佳实践:始终使用 password_hash()password_verify() ——它们是 PHP 官方维护的安全抽象层。
// ✅ 安全示例:注册时哈希密码
$password = "MyS3cur3P@ss!";
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// 输出类似:"$2y$12$X9z...A7BqJvQ..."

// ✅ 登录时验证
if (password_verify($inputPassword, $hash)) {
    echo "登录成功!";
} else {
    echo "密码错误。";
}

// ✅ 可检测哈希是否过期并重新哈希(升级成本)
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 14])) {
    $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 14]);
}

总结建议

  • 绝对避免md5()sha1()crypt()(无参数)、手写盐逻辑;
  • 谨慎使用hash('sha256', ...) 仅限非密码场景(如校验文件完整性);
  • 首选方案password_hash() / password_verify() ——简洁、安全、未来兼容(PHP 可能默认切换为 Argon2)。

记住:安全不是功能,而是持续的习惯。从今天起,让每一行密码处理代码都通过 password_hash() 的考验。

```