PHP 哈希算法在密码存储中的应用
在 Web 应用开发中,安全地存储用户密码是开发者不可推卸的责任。明文存储密码是严重安全隐患,而使用强哈希算法加盐(salt)处理则是行业标准实践。PHP 提供了内置函数,让安全密码哈希变得简单可靠。
为什么不能用普通哈希函数?
md5() 或 sha1() 等快速哈希算法已被证明不适用于密码存储——它们计算太快,易受彩虹表和暴力破解攻击。现代密码哈希需具备慢速性、抗碰撞性与内置加盐机制。
推荐方案:PHP 的 password_* 函数族
自 PHP 5.5 起,password_hash() 和 password_verify() 成为密码哈希的黄金标准。它们默认使用 bcrypt 算法(PHP 7.2+ 支持 Argon2i),自动处理加盐、迭代轮数等细节:
<?php
// ✅ 安全:注册时哈希密码
$password = "MySecureP@ssw0rd!";
$hash = password_hash($password, PASSWORD_ARGON2ID, [
'memory_cost' => 65536, // 64MB 内存
'time_cost' => 4,
'threads' => 3
]);
echo "哈希值: $hash\n"; // 输出类似: $argon2id$v=19$m=65536,t=4,p=3$...
// ✅ 安全:登录时验证密码
if (password_verify("MySecureP@ssw0rd!", $hash)) {
echo "验证成功!\n";
} else {
echo "密码错误。\n";
}
// 🔍 可检查哈希是否需要重新哈希(如算法升级)
if (password_needs_rehash($hash, PASSWORD_ARGON2ID, ['time_cost' => 6])) {
$hash = password_hash($password, PASSWORD_ARGON2ID, ['time_cost' => 6]);
}
?>
✅ 最佳实践提示:
• 永远使用
• 存储哈希值时保留完整字符串(含算法、参数、盐),长度约 90–120 字符,请确保数据库字段为
• 验证一律用
• 永远使用
password_hash() 而非手动加盐 + hash()• 存储哈希值时保留完整字符串(含算法、参数、盐),长度约 90–120 字符,请确保数据库字段为
VARCHAR(255)• 验证一律用
password_verify(),它会自动解析盐与参数
兼容性与迁移建议
若项目仍在使用旧版 PHP,可引入 password_compat 库(Composer 安装:ircmaxell/password-compat)。对于遗留系统迁移,可逐步将旧哈希升级为新格式:
<?php
// 登录流程中无缝升级哈希
if (password_verify($inputPassword, $storedHash)) {
if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID)) {
$newHash = password_hash($inputPassword, PASSWORD_ARGON2ID);
// 更新数据库中的密码哈希
updatePasswordHash($userId, $newHash);
}
// 允许登录...
}
?>
⚠️ 绝对禁止:
• 使用
• 自行拼接盐(如
• 将哈希结果截断或 Base64 编码后存储(破坏完整性)
• 使用
md5($pass)、sha1($pass) 或 crypt($pass)(无显式盐)• 自行拼接盐(如
md5($salt . $pass))——盐管理与算法演进难以保障• 将哈希结果截断或 Base64 编码后存储(破坏完整性)
安全不是功能,而是基石。PHP 的 password_* 函数以极简 API 封装了密码学最佳实践。从今天起,请让每一行密码处理代码,都经得起专业审计的审视。