在 PHP 中进行密码哈希和验证时,crypt() 和 password_verify() 是两个经常被提及的函数。虽然它们都涉及密码安全处理,但它们的使用方式和设计目的有所不同。因此,开发者可能会疑问:
crypt() 是 PHP 早期用于加密密码的函数。它支持多种算法,如:
DES(默认)
MD5(以 $1$ 开头)
Blowfish(以 $2a$, $2y$ 等开头)
SHA-256、SHA-512(以 $5$, $6$ 开头)
一个典型的 crypt() 用法如下:
$password = 'mySecret';
$salt = '$2y$10$' . substr(strtr(base64_encode(random_bytes(16)), '+', '.'), 0, 22);
$hash = crypt($password, $salt);
password_verify() 是在 PHP 5.5 引入的,专门为验证使用 password_hash() 生成的哈希设计的函数。它自动识别哈希使用的算法(如 Bcrypt、Argon2)并根据输入的明文密码进行比对。
if (password_verify('mySecret', $hashFromDatabase)) {
echo '密码正确';
}
简短回答:不建议,也没有意义。
虽然 password_verify() 背后确实是调用了类似 crypt() 的底层机制,但它只支持其“自家”函数 password_hash() 生成的哈希格式。如果你使用 crypt() 自定义哈希,再使用 password_verify() 来验证,会出现以下问题:
如果哈希格式不符合 password_verify() 预期,它将返回 false;
PHP 内部并没有保证未来版本对 crypt() 生成的非标准格式哈希的支持;
password_verify() 对于错误格式的哈希可能根本无法解析,导致验证始终失败。
换句话说,两者虽有关联,但不是设计为互通的函数对。
手动管理盐值和算法选择,易出错;
如果使用不当(如使用默认 DES 算法或弱盐值),容易遭受暴力破解;
不具备自动更新算法的机制;
未来兼容性无法保证。
自动选择安全默认算法(如 Bcrypt);
自动生成盐值;
算法封装良好,开发者无需关心底层实现;
可通过 password_needs_rehash() 实现平滑算法升级;
安全性经过现代标准审查。
为了获得更好的安全性和未来兼容性,建议始终使用 password_hash() 与 password_verify() 搭配使用:
// 注册或修改密码时
$hash = password_hash('mySecret', PASSWORD_DEFAULT);
// 登录时验证
if (password_verify('mySecret', $hash)) {
// 验证成功
}
如果你在旧系统中使用了 crypt(),建议在用户登录成功后,使用 password_hash() 重新生成哈希,并更新数据库中的值。这种方式可以逐步平滑过渡到更安全的加密方法。
虽然 crypt() 是 PHP 中的一员老将,但在密码处理领域,它已经逐渐被更现代、更安全的 password_hash() 和 password_verify() 所取代。将 crypt() 和 password_verify() 结合使用并不能带来预期的安全性提升,反而可能因不兼容而带来验证失败等问题。因此,最佳实践是完全采用 PHP 提供的 password_ 系列函数来处理用户密码*,确保系统的安全性与可维护性。
如需更进一步的安全措施,可以结合使用 Argon2 算法: