Этот вопрос связан с реализацией PHP crypt()
. По этому вопросу первые 7 символов соли не учитываются, поэтому соль "$2a$07$a
" будет иметь длину 1, так как это всего лишь 1 символ соли и семь символов метаданных.
При использовании сольных строк длиной более 22 символов не изменяется изменение хэша (т.е. усечение), и при использовании строк длиной менее 21 символа соль будет автоматически дополняться (с символами < <22 > ); это довольно просто. Однако, если задана соль 20 символов и соль 21 символа, где эти два идентичны, за исключением окончательного символа соли длиной 21 длины, обе хешированные строки будут одинаковыми. Соль длиной 22 символа, которая идентична соли длины 21, за исключением конечного символа, хэш снова будет другим.
Пример в коде:
$foo = 'bar';
$salt_xx = '$2a$07$';
$salt_19 = $salt_xx . 'b1b2ee48991281a439d';
$salt_20 = $salt_19 . 'a';
$salt_21 = $salt_20 . '2';
$salt_22 = $salt_21 . 'b';
var_dump(
crypt($foo, $salt_19),
crypt($foo, $salt_20),
crypt($foo, $salt_21),
crypt($foo, $salt_22)
);
Будет производить:
string(60) "$2a$07$b1b2ee48991281a439d$$.dEUdhUoQXVqUieLTCp0cFVolhFcbuNi"
string(60) "$2a$07$b1b2ee48991281a439da$.UxGYN739wLkV5PGoR1XA4EvNVPjwylG"
string(60) "$2a$07$b1b2ee48991281a439da2.UxGYN739wLkV5PGoR1XA4EvNVPjwylG"
string(60) "$2a$07$b1b2ee48991281a439da2O4AH0.y/AsOuzMpI.f4sBs8E2hQjPUQq"
Почему это?
EDIT:
Некоторые пользователи отмечают, что существует разница в общей строке, что верно. В salt_20
смещение (28, 4) составляет da$.
, а в salt_21
смещение (28, 4) равно da2.
; однако важно отметить, что генерируемая строка включает в себя хеш, соль, а также инструкции для получения соли (т.е. $2a$07$
); часть, в которой происходит различие, по-прежнему остается солью. Фактический хэш не изменяется как UxGYN739wLkV5PGoR1XA4EvNVPjwylG
.
Таким образом, на самом деле это не разница в хеш-генерации, а разница в соли, используемой для хранения хеша, что и есть проблема: две соли генерируют один и тот же хэш.
Rembmer: выход будет в следующем формате:
"$2a$##$saltsaltsaltsaltsaltsaHASHhashHASHhashHASHhashHASHhash"
// ^ Hash Starts Here, offset 28,32
где ## - это логарифмическая база-2, определяющая количество итераций, выполняемых алгоритмом для
Изменить 2:
В комментариях было предложено добавить дополнительную информацию, так как пользователь не смог воспроизвести мой вывод. Выполнение следующего кода:
var_dump(
PHP_VERSION,
PHP_OS,
CRYPT_SALT_LENGTH,
CRYPT_STD_DES,
CRYPT_EXT_DES,
CRYPT_MD5,
CRYPT_BLOWFISH
);
Производит следующий вывод:
string(5) "5.3.0"
string(5) "WINNT"
int(60)
int(1)
int(1)
int(1)
int(1)
Надеюсь, что это поможет.