Правильно ли я использую CRYPT_BLOWFISH в PHP?

Я собираюсь использовать это для системы паролей пользователей, но сначала хочу убедиться, что делаю это правильно. Вот мой тестовый код:

function generateBlowfishSalt() {
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./';
    $numChars = strlen($chars);
    $salt = '';

    for($i = 0; $i < 22; ++$i) {
        $salt .= $chars[mt_rand(0, $numChars - 1)];
    }

    return $salt;
}

$password = 'foo';
$salt = generateBlowfishSalt();
$hash1 = crypt($password, '$2a$12$' . $salt);
$hash2 = crypt($password, $hash1);
$compare = ($hash1 == $hash2);

printf('password: %s</br>', $password);
printf('salt: %s</br>', $salt);
printf('hash1: %s</br>', $hash1);
printf('hash2: %s</br>', $hash2);
printf('compare: ' . $compare);

Вот пример вывода:

password: foo
salt: MYVJ32OqLcMGBar3pUa.0S
hash1: $2a$12$MYVJ32OqLcMGBar3pUa.0OTRwv6UX0bcxnSmheKOcqjvqvCrM/p2q
hash2: $2a$12$MYVJ32OqLcMGBar3pUa.0OTRwv6UX0bcxnSmheKOcqjvqvCrM/p2q
compare: 1

Мои основные вопросы:

  1. Правильно ли я генерирую 22-символьную соль? Некоторые реализации, которые я видел, используют base64_encode() для генерации соли. Нужно ли мне это делать?

  2. Правильно ли хранить все значение $hash1 в базе данных, а не хранить отдельное значение соли, поскольку $hash1 будет содержать соль, и это все, что мне нужно для проверки пароля?

  3. На странице документа PHP crypt() пример CRYPT_BLOWFISH имеет конечный $ для аргумента соли (это: '$2a$07$usesomesillystringforsalt$'). Но во всех примерах, которые я видел, никто не использует конечный $. Это необязательно?

Спасибо


person Ryan    schedule 20.05.2012    source источник


Ответы (1)


Вы делаете соль правильно. Просто должен быть случайным. Существует множество различных методов случайной генерации этого. Некоторые люди используют его в дополнение к дате и т. Д. Кроме того, более длинные соли не имеют большого значения, поскольку они все равно будут обрезаны. Это требует определенной длины, по крайней мере, с точки зрения crypt(). Так что, если немного дополнительной набивки заставляет вас чувствовать себя лучше, сделайте это.

Вы предполагаете хранить соль в базе данных. Сначала мне было трудно это понять. Весь смысл соли заключается только в том, что для радужной таблицы паролей требуется больше времени с огромным списком возможных паролей. Исправление, кроме того, также помогает при 2 или более одинаковых паролях, что обязательно произойдет. Если это так, хэши все равно будут отличаться из-за случайных солей.

Что касается crypt(), продолжайте тестировать его до тех пор, пока он не будет выглядеть и иметь ту же длину, что и в php DOC для PHP, но да, он выглядит правильно.

person Andy    schedule 20.05.2012
comment
Разве соль не случайна? Я использую mt_rand() для его создания. Я не думаю, что мне нужно хранить отдельное значение соли поверх значения, возвращаемого crypt(), потому что значение, возвращаемое crypt(), содержит почти всю соль. Более того, мне нужно только значение, возвращаемое первым вызовом crypt(), чтобы проверить пароль. - person Ryan; 20.05.2012
comment
Да ничего дополнительно делать не нужно. Вы генерируете случайную соль. Я почти уверен, что сказал, что вы делаете соль правильно. Просто повторяю. У вас правильные идеи. - person Andy; 21.05.2012