CRYPT_BLOWFISH 中盐的长度

mso*_*soa 4 php bcrypt

在 PHP 手册中指出:

CRYPT_BLOWFISH - Blowfish 使用盐进行散列,如下所示:“$2a$”,一个两位数的成本参数,“$”,以及来自字母表“./0-9A-Za-z”的 22 位数字。

我意识到长度是 22。我编写了以下代码并注意到salt的输出长度是21

$encoded = crypt('pass','$2a$08$QAZXSWEDCVFRTGBNHYUJMK'); // Lenght of Q . . . K is 22
echo $encoded;
Run Code Online (Sandbox Code Playgroud)

输出:

$2a$08$QAZXSWEDCVFRTGBNHYUJM./CR85.t4YytTnmLXsRJMfbYWopbT8Nu

K中不存在:QAZXSWEDCVFRTGBNHYUJM

有什么我不明白的吗?

Gum*_*mbo 5

这是由于盐是如何编码的。实际盐是 128 位,但crypt格式中的编码盐是 22 个字符·8 位/字符·3/4 = 132 位。所以实际上没有使用 4 位编码盐。

这也意味着有 16 个编码的盐会产生相同的哈希值,因为它们的最低有效字符的前四位是相同的:

$hashes = array();
$chars = array_merge(array('.','/'), range('A','Z'), range('a','z'), range('0','9'));
foreach ($chars as $char) {
    $salt = 'QAZXSWEDCVFRTGBNHYUJM'.$char;
    $hashes[$salt] = crypt('pass','$2a$08$'.$salt);
}
var_dump($hashes);
Run Code Online (Sandbox Code Playgroud)

以下是产生相同散列的编码盐:

QAZXSWEDCVFRTGBNHYUJM.
QAZXSWEDCVFRTGBNHYUJM/
QAZXSWEDCVFRTGBNHYUJMA
QAZXSWEDCVFRTGBNHYUJMB
QAZXSWEDCVFRTGBNHYUJMC
QAZXSWEDCVFRTGBNHYUJMD
QAZXSWEDCVFRTGBNHYUJME
QAZXSWEDCVFRTGBNHYUJMF
QAZXSWEDCVFRTGBNHYUJMG
QAZXSWEDCVFRTGBNHYUJMH
QAZXSWEDCVFRTGBNHYUJMI
QAZXSWEDCVFRTGBNHYUJMJ
QAZXSWEDCVFRTGBNHYUJMK
QAZXSWEDCVFRTGBNHYUJML
QAZXSWEDCVFRTGBNHYUJMM
QAZXSWEDCVFRTGBNHYUJMN
Run Code Online (Sandbox Code Playgroud)

crypt可能只是使用第一个编码内部使用的 128 位盐,即QAZXSWEDCVFRTGBNHYUJM..