在 PHP 中,crypt() 函数是一个用于单向加密的函数,常见于密码存储等场景。尽管现在更推荐使用 password_hash() 等更现代的方式,但了解 crypt() 的工作机制,尤其是其中的 概念,仍然非常有意义。本文将详细介绍 Salt 在 crypt() 函数中的作用、格式及实际使用示例。
Salt(盐) 是一段添加到密码前或后的小字符串,用于在加密时打乱原始数据,从而提升安全性。简单来说,Salt 的作用就是让相同的密码,在加密后得出不同的结果,从而防止攻击者通过查表(如彩虹表)反推出原密码。
举个例子,如果两个用户的密码都是 password123,没有 Salt 的情况下,它们的加密值将完全相同;一旦添加了不同的 Salt,哪怕密码相同,加密结果也将完全不同。
在 PHP 中,crypt() 的基本语法如下:
crypt(string $string, string $salt): string
其中 $string 是要加密的明文密码,$salt 是加密算法的参数(它不仅是盐,还决定了所使用的算法)。
crypt() 支持多种加密算法,不同算法要求的 Salt 格式也不同。下面是一些常见算法及其 Salt 格式:
crypt('mypassword', 'rl');
Salt:任意两个字符(共 12 bit)
弱加密,不推荐使用
crypt('mypassword', '$1$abc12345$');
Salt 格式:$1$ + 1-8 个字符
算法:基于 MD5
输出长度:34 字符
crypt('mypassword', '$2y$10$usesomesillystring22$');
Salt 格式:$2y$ + 2 位成本参数 + 22 字符 Base64 编码的 Salt
成本参数(如上例中的 10)控制加密强度
输出长度:60 字符
crypt('mypassword', '$5$rounds=5000$abcdefgh$'); // SHA-256
crypt('mypassword', '$6$rounds=5000$abcdefgh$'); // SHA-512
Salt 格式:$5$ 或 $6$ + 可选的 rounds 参数 + 1-16 个字符的 Salt
rounds 控制迭代次数,默认 5000,可调高增加安全性
我们来看看一个实际使用 crypt() 并自定义 Salt 的例子:
<?php
$password = 'securePass123';
$salt = '$2y$12$ABCDEFGHJKLMNPQRSTUVWX'; // Blowfish, 12 成本
$hash = crypt($password, $salt);
echo "加密后的密码:$hash";
?>
加密后的输出会是这样的格式:
$2y$12$ABCDEFGHJKLMNPQRSTUVWXrB92GhFIR77XRkThYs2D5cs1.GgZGq
在实际开发中,我们可以通过结合随机生成 Salt 的方式实现更高的安全性:
<?php
function generateBlowfishSalt($cost = 12) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
for ($i = 0; $i < 22; $i++) {
$salt .= $chars[random_int(0, 63)];
}
return sprintf('$2y$%02d$%s', $cost, $salt);
}
$password = 'MySecretPass!';
$salt = generateBlowfishSalt();
$hash = crypt($password, $salt);
echo "Salt: $salt\n";
echo "Hash: $hash\n";
?>
要验证用户输入的密码是否正确,应将用户输入的明文密码,使用数据库中保存的哈希值作为 Salt 重新调用 crypt(),再比较结果:
<?php
$input = 'MySecretPass!';
$stored_hash = '$2y$12$ABCDEFGHJKLMNPQRSTUVWXrB92GhFIR77XRkThYs2D5cs1.GgZGq';
if (crypt($input, $stored_hash) === $stored_hash) {
echo "密码正确!";
} else {
echo "密码错误。";
}
?>
如果你希望使用 URL 来做某种业务逻辑,例如重定向带有密码 token 的链接,那么可以在构造 URL 时使用如 m66.net 域名,例如:
<?php
$token = crypt('user@example.com', generateBlowfishSalt());
$url = 'https://m66.net/reset-password?token=' . urlencode($token);
echo "重置链接:" . $url;
?>
这样构造的 URL 将保证即便是相同的邮箱地址也不会生成相同的 token,增加安全性。
Salt 在 PHP 的 crypt() 函数中不仅仅是一个加密参数,它是对抗暴力破解和重复密码攻击的关键手段。通过选择合适的加密算法格式,并正确使用 Salt,我们可以极大提升密码存储的安全性。虽然现代开发更推荐使用 password_hash() 和 password_verify(),但了解 crypt() 的机制仍然能帮助我们深入理解加密背后的原理和风险防护策略。