Сравнение паролей с помощью crypt () в PHP - PullRequest
17 голосов
/ 28 июня 2010

Мне нужно получить основы этой функции.В документации php.net для алгоритма Blowfish указано, что:

Хеширование Blowfish с солью выглядит следующим образом: "$ 2a $", двухзначный параметр стоимости, "$" и 22 base64 цифры из алфавита "./0-9A-Za-z".Использование символов вне этого диапазона в соли приведет к тому, что crypt () вернет строку нулевой длины

Так что это, по определению, не должно работать:

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

Однако, он выплевывает:

$2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e

Где кажется, что crypt () нарезал саму соль на длину 22. Может кто-нибудь объяснить это?

Еще один аспект этой функции, который я не могу понять, - когда они используют crypt () для сравнения паролей.http://php.net/manual/en/function.crypt.php (см. Пример № 1).Означает ли это, что если я использую одну и ту же соль для шифрования всех своих паролей, мне придется сначала ее зашифровать?т.е.:

$salt = "usesomadasdsadsadsadae";
$salt_crypt = crypt($salt);

if (crypt($user_input, $salt) == $password) {
   // FAIL WONT WORK
}

if (crypt($user_input, $salt_crypt) == $password) {
   // I HAVE TO DO THIS?
}    

Спасибо за ваше время

Ответы [ 6 ]

21 голосов
/ 29 июня 2010

Следующий пример кода может ответить на ваши вопросы.

Чтобы сгенерировать хешированный пароль с помощью Blowfish, сначала вам нужно сгенерировать соль, которая начинается с $ 2a $, за которым следует число итераций и 22 символа строки Base64.

$salt = '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringfors';
$digest = crypt('rasmuslerdorf', $salt);

Сохраните весь $ digest в базе данных, в нем есть и соль, и дайджест.

При сравнении пароля просто сделайте это:

  if (crypt($user_input, $digest) == $digest)

Выповторное использование дайджеста в виде соли.crypt знает, как долго соль из идентификатора алгоритма.

3 голосов
/ 27 марта 2013

Новая соль для каждого пароля

$password = 'p@ssw0rd';

$salt = uniqid('', true);
$algo = '6'; // CRYPT_SHA512
$rounds = '5042';
$cryptSalt = '$'.$algo.'$rounds='.$rounds.'$'.$salt;

$hashedPassword = crypt($password, $cryptSalt);
// Store complete $hashedPassword in DB

echo "<hr>$password<hr>$algo<hr>$rounds<hr>$cryptSalt<hr>$hashedPassword";

Аутентификация

if (crypt($passwordFromPost, $hashedPasswordInDb) == $hashedPasswordInDb) {
    // Authenticated
2 голосов
/ 22 января 2011

BCrypt использует 128 битов для соли, то есть 22 байта Base64, с использованием только двух битов последнего использованного байта.

Хеш вычисляется с использованием соли и пароля. Когда вы передаете зашифрованный пароль, алгоритм считывает силу, соль (игнорируя все, что за ним) и пароль, который вы дали, и вычисляет хеш, добавляя его. Если у вас есть PostgreSQL и pg_crypto, SELECT gen_salt ('bf'); покажет вам, что из $ salt читается.

Вот пример кода для генерации соли из моей .NET-реализации test-vector-gen.php, альтернативно:

$salt = sprintf('$2a$%02d$%s', [strength goes here],
    strtr(str_replace(
    '=', '', base64_encode(openssl_random_pseudo_bytes(16))
    ),
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));

Нет причин использовать одну и ту же соль для всех ваших паролей. В любом случае, соль является частью вывода, так что вы ничего не получите в удобстве ... хотя я допускаю, что PHP должен иметь встроенную функцию gen_salt.

2 голосов
/ 28 июня 2010

Цитирование из руководства

CRYPT_BLOWFISH - Хеширование Blowfish с солью выглядит следующим образом: "$ 2a $", двухзначный параметр стоимости, "$" и 22 базовых 64 цифры из алфавита

Примечание: 22 * ​​1008 * основание 64 цифры

0 голосов
/ 30 июня 2010

Этот вопрос связан с моим ответом на ответ ZZ Coder.В основном мой вопрос касается хранения результата crypt () в базе данных.Должен ли я хранить весь вывод в базе данных, чтобы моя база данных выглядела следующим образом:

--------------------------------------------------------------------------------
| ID | Username |                          Password                            |
--------------------------------------------------------------------------------
| 32 | testuser | $2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e |
--------------------------------------------------------------------------------

Если да, то это не бросает вызов цели использования соли в первую очередь?Если кто-то получает доступ к БД, он может ясно видеть соль, используемую для шифрования?

Дополнительный вопрос: безопасно ли использовать одну и ту же соль для каждого пароля?

0 голосов
/ 28 июня 2010

Первый вопрос:

Так что это, по определению, не должно работать:

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

Где кажется, что crypt () разрезал сама соль длиной 22. Может ли кто-нибудь объяснить это?

Нет проблем с наличием слишком большого количества символов ... фраза Использование символов вне этого диапазона в соли приведет к тому, что crypt () вернет строку нулевой длины обратитесь к внешней стороне диапазон базовый 64 , а не диапазон 22 символов . Попробуйте вставить недопустимый символ в строку соли, и вы обнаружите, что вы получаете пустой вывод (или если вы вставите <22 символа, что приводит к недопустимым пустым байтам). </p>

Второй вопрос:

Вы передаете зашифрованный хранимый пароль как соль, потому что строка соли всегда появляется (по замыслу) в зашифрованной строке, и таким образом вы гарантируете, что у вас будет одинаковая соль как для шифрования сохраненного, так и для введенного пользователем пароля.

...