Длина соли в CRYPT_BLOWFISH

В руководстве PHP указано, что:

CRYPT_BLOWFISH – хеширование Blowfish с солью следующим образом: «$ 2a $», двухзначный параметр стоимости, «$» и 22 цифры из алфавита «./0-9A-Za-z».

Я понял, что длина соли равна 22 . Я написал следующий код и заметил, что в выходной длине соли 21 .

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

Вывод:

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

K не существует в соли : QAZXSWEDCVFRTGBNHYUJM

Что-то я не понимаю?

Это связано с тем, как соль кодируется. Фактическая соль составляет 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); 

Вот закодированные соли, которые приводят к одному и тому же хэшу:

 QAZXSWEDCVFRTGBNHYUJM. QAZXSWEDCVFRTGBNHYUJM/ QAZXSWEDCVFRTGBNHYUJMA QAZXSWEDCVFRTGBNHYUJMB QAZXSWEDCVFRTGBNHYUJMC QAZXSWEDCVFRTGBNHYUJMD QAZXSWEDCVFRTGBNHYUJME QAZXSWEDCVFRTGBNHYUJMF QAZXSWEDCVFRTGBNHYUJMG QAZXSWEDCVFRTGBNHYUJMH QAZXSWEDCVFRTGBNHYUJMI QAZXSWEDCVFRTGBNHYUJMJ QAZXSWEDCVFRTGBNHYUJMK QAZXSWEDCVFRTGBNHYUJML QAZXSWEDCVFRTGBNHYUJMM QAZXSWEDCVFRTGBNHYUJMN 

crypt вероятно, просто использует первую, которая кодирует внутренне используемую 128-битную соль, которая является QAZXSWEDCVFRTGBNHYUJM. ,