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

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

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

在用户认证系统中,**安全地存储密码**是开发者的第一道防线。错误的加密方式可能让整个应用暴露于严重风险之中。本文简明对比三种常见方案:MD5、SHA 系列与现代推荐方案 password_hash()(基于 bcrypt)。

❌ MD5:已淘汰,绝不用于密码

MD5 是哈希算法,但不是加密算法,且早已被证明存在严重碰撞漏洞。它无盐值、计算极快,极易被彩虹表或暴力破解。

// ❌ 危险示例(仅作演示,切勿使用!)
$password = "123456";
$md5_hash = md5($password); // "e10adc3949ba59abbe56e057f20f883e"

❌ SHA-1 / SHA-256:仍不适用于密码

SHA 系列虽比 MD5 更安全,但仍是快速哈希函数——攻击者可每秒尝试数亿次。若未加盐且重复使用,依然脆弱。

// ❌ 不推荐(缺乏自适应成本控制)
$sha256 = hash('sha256', '123456' . 'static_salt'); // 静态盐值易被预计算

✅ bcrypt:PHP 原生推荐方案

PHP 自 5.5+ 内置 password_hash()password_verify(),默认使用 bcrypt 算法。其核心优势:

  • 自动加盐(salt),每次调用生成唯一哈希
  • 可调节计算成本(cost factor),抵御算力提升
  • 抗 GPU/ASIC 暴力破解(设计为计算密集型)
  • 验证逻辑简单安全,无需手动处理盐值
// ✅ 正确做法:一行生成,一行验证
$password = "MySecureP@ssw0rd!";

// 生成哈希(默认 cost=10,可指定如 ['cost' => 12])
$hash = password_hash($password, PASSWORD_BCRYPT);
// 示例输出:"$2y$10$9ZvzVQx...(60字符,含算法、cost、salt和哈希)"

// 验证时直接比对原文 —— 自动提取 salt 并重算
if (password_verify($password, $hash)) {
    echo "登录成功!";
} else {
    echo "密码错误。";
}
✅ 最佳实践提示:
• 始终使用 password_hash() + password_verify()
• 无需存储 salt —— 它已编码在哈希字符串中
• 定期升级 cost 参数(如从 10 → 12)以应对硬件进步
• PHP 8.0+ 还支持 PASSWORD_ARGON2I/PASSWORD_ARGON2ID(需 libsodium)
⚠️ 特别注意:
md5()sha1()crypt()(未配 bcrypt)等函数均不应再用于密码
• “加盐 MD5” 或 “SHA256 + 时间戳” 仍是伪安全,无法替代自适应哈希
• 永远不要自己实现密码哈希逻辑 —— 使用经过审计的原生函数

总结:安全不是功能,而是持续实践。从今天起,请用 password_hash() 替代所有老旧哈希方案——这是 PHP 社区十年验证的最佳答案。

```