PHP 中的 crypt() 函数是一个用于加密字符串(通常是密码)的核心函数。它基于系统底层的加密算法,通过对输入字符串进行哈希处理,实现密码的安全存储和验证。虽然 crypt() 函数的基本用法和目的在各个 PHP 版本中保持一致,但其内部实现及支持的算法随着 PHP 和操作系统版本的变化,存在一些重要差异。这些差异会直接影响密码的安全性和应用的兼容性,理解它们对开发安全稳定的应用至关重要。
crypt() 接受两个参数:
$hashed_password = crypt($password, $salt);
$password 是明文密码或任意字符串;
$salt 是用来控制加密算法的盐值(salt),格式不同决定了加密算法的选择。
返回值是经过加密处理后的字符串。验证密码时,一般会用相同的盐重新加密输入密码,比较结果是否一致。
早期 PHP 版本(PHP 4.x、PHP 5.2 及之前)
只支持系统提供的标准 DES 加密(基于 56 位密钥,盐为 2 字符),安全性较低。
如果提供的盐格式不正确,crypt() 会退化为使用 DES 加密。
PHP 5.3 及以后
开始支持更现代的加密算法,如 MD5(盐格式以 $1$ 开头),
还支持 Blowfish(盐格式以 $2a$ 或 $2y$ 开头,取决于 PHP 版本)、
SHA-256 ($5$) 和 SHA-512 ($6$) 等算法,前提是操作系统的 libc 库支持。
PHP 7.x
继续完善 Blowfish 支持,修复了历史上的一些安全漏洞(如 $2a$ 的漏洞影响)
PHP 7.3 以后引入 $2y$ 标记,更安全的 Blowfish 版本。
对不同系统的支持程度更高,支持更多算法。
PHP 8.x
保持对上述算法的支持,注重安全性和兼容性。
推荐使用 PHP 原生的密码哈希函数 password_hash() 和 password_verify(),但 crypt() 依然可用。
crypt() 函数实际上是依赖操作系统的 libc 库(如 GNU libc、BSD libc)来完成加密运算,因此:
同样的 PHP 版本在不同操作系统(Linux、FreeBSD、Windows)上,支持的算法可能不完全一致。
Windows 上 crypt() 支持非常有限,通常只支持传统的 DES 加密。
Linux 通常支持多种算法,取决于 libc 版本。
不同加密算法的安全性差距巨大。早期的 DES 加密算法极易被破解,不应再用于生产环境。支持现代算法(如 Blowfish、SHA-512)的 PHP 版本和操作系统,可以极大提升密码存储的安全性。
如果应用依赖 crypt() 并且没有明确指定盐的格式,升级 PHP 版本或迁移操作系统时可能出现密码验证失败。
例如,旧系统只用 DES 加密,迁移后变为 SHA-512,导致新系统无法正确验证旧密码。
因此,建议应用中明确指定盐格式,或者采用更现代的密码处理接口。
PHP 官方在 5.5 版本引入了 password_hash() 和 password_verify(),封装了密码加密和验证的细节:
$hash = password_hash($password, PASSWORD_DEFAULT); // 默认使用 bcrypt
if (password_verify($password, $hash)) {
echo "密码验证成功";
}
该接口兼容性好,安全性高,能自动选择最安全的算法。
避免了直接使用 crypt() 的复杂性和兼容性问题。
未来版本推荐使用此方案替代直接调用 crypt()。
下面示例展示如何用不同的盐调用 crypt(),并说明加密结果的差异: