PHP 密码加密方案对比:MD5、SHA、bcrypt
在用户认证系统中,**安全地存储密码**是开发者的第一道防线。错误的加密方式可能让整个系统暴露于严重风险之中。本文对比三种常见方案:MD5、SHA 系列(如 SHA-256)与现代推荐的 password_hash()(基于 bcrypt)。
❌ MD5:已淘汰,绝不用于密码
MD5 是哈希算法,但不是加密算法,且早已被证明存在严重碰撞漏洞。它无盐值、计算极快,极易被彩虹表或暴力破解。
// ❌ 危险示例(仅作演示,切勿使用!)
$password = "123456";
$md5_hash = md5($password); // "e10adc3949ba59abbe56e057f20f883e"
echo $md5_hash;
⚠️ SHA-256/SHA-512:比 MD5 强,但仍不推荐
SHA 系列抗碰撞性强,但仍是**快速哈希**——攻击者可用 GPU 每秒尝试数十亿次。若未加盐(salt),仍易受预计算攻击。
// ⚠️ 不推荐:手动加盐 + SHA-256(易出错且不够慢)
$salt = bin2hex(random_bytes(16));
$hash = hash('sha256', $salt . $password);
// 存储 $salt 和 $hash —— 但缺少迭代次数控制与标准化格式
✅ bcrypt:PHP 官方推荐的现代方案
PHP 内置的 password_hash() 默认使用 bcrypt 算法:自动加盐、可调成本因子(默认 cost=10)、抗 GPU/ASIC 攻击,且格式兼容未来升级(如将来支持 Argon2)。
// ✅ 推荐:一行代码完成安全哈希
$password = "MySecureP@ssw0rd!";
$hash = password_hash($password, PASSWORD_DEFAULT);
// 示例输出:"$2y$10$9zIqLmRjVX...(含 salt 与 cost)"
// 验证时无需关心盐值或算法细节
if (password_verify($password, $hash)) {
echo "验证成功!";
}
✅ 最佳实践:始终使用
password_hash() 与 password_verify();
用 PASSWORD_DEFAULT(当前为 bcrypt,未来自动升级);
若需固定算法,可选 PASSWORD_BCRYPT 并显式设置 cost(如 ['cost' => 12])。
❗ 注意:不要自己实现加盐、迭代或算法选择——PHP 的密码函数已通过严格安全审计,重复造轮子是最大风险来源。
总结:MD5 已成历史遗迹;SHA 系列适合校验文件完整性,而非密码;bcrypt(通过 password_hash)是 PHP 中存储密码的黄金标准。安全不是功能,而是持续的敬畏与正确实践。