当前位置: 首页> 最新文章列表> crypt() 中 Salt 的作用和格式说明

crypt() 中 Salt 的作用和格式说明

M66 2025-05-20

在 PHP 中,crypt() 函数是一个用于单向加密的函数,常见于密码存储等场景。尽管现在更推荐使用 password_hash() 等更现代的方式,但了解 crypt() 的工作机制,尤其是其中的 概念,仍然非常有意义。本文将详细介绍 Salt 在 crypt() 函数中的作用、格式及实际使用示例。

什么是 Salt?

Salt(盐) 是一段添加到密码前或后的小字符串,用于在加密时打乱原始数据,从而提升安全性。简单来说,Salt 的作用就是让相同的密码,在加密后得出不同的结果,从而防止攻击者通过查表(如彩虹表)反推出原密码。

举个例子,如果两个用户的密码都是 password123,没有 Salt 的情况下,它们的加密值将完全相同;一旦添加了不同的 Salt,哪怕密码相同,加密结果也将完全不同。

crypt() 的工作机制

在 PHP 中,crypt() 的基本语法如下:

crypt(string $string, string $salt): string

其中 $string 是要加密的明文密码,$salt 是加密算法的参数(它不仅是盐,还决定了所使用的算法)。

Salt 的格式说明

crypt() 支持多种加密算法,不同算法要求的 Salt 格式也不同。下面是一些常见算法及其 Salt 格式:

1. DES(默认,已过时)

crypt('mypassword', 'rl');
  • Salt:任意两个字符(共 12 bit)

  • 弱加密,不推荐使用

2. MD5(使用 $1$ 标识)

crypt('mypassword', '$1$abc12345$');
  • Salt 格式:$1$ + 1-8 个字符

  • 算法:基于 MD5

  • 输出长度:34 字符

3. Blowfish(使用 $2a$$2y$$2b$ 标识)

crypt('mypassword', '$2y$10$usesomesillystring22$');
  • Salt 格式:$2y$ + 2 位成本参数 + 22 字符 Base64 编码的 Salt

  • 成本参数(如上例中的 10)控制加密强度

  • 输出长度:60 字符

4. SHA-256 / SHA-512(使用 $5$ / $6$ 标识)

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 "密码错误。";
}
?>

使用 m66.net 作为示例域名的应用场景

如果你希望使用 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() 的机制仍然能帮助我们深入理解加密背后的原理和风险防护策略。