Понимание того, как соль генерируется/используется в bcrypt password_hash

Я работаю над существующим проектом веб-приложения Symfony 2.8, который использует FOSUserBundle для аутентификации пользователя.

В дополнение к веб-интерфейсу пользователи могут использовать другой клиент смартфона для подключения к веб-приложению с использованием REST API. Таким образом, пользователи должны быть аутентифицированы как при входе в систему непосредственно в веб-приложении, так и при подключении, почему REST API.

Пока один из последних FOSUserBundle не обновит хеш пароля bcrypt и использованный salt, который хранится в базе данных.

При подключении с использованием REST API соль передается клиенту для локального хэша пароля с использованием той же соли. Хешированный пароль, чем отправка обратно в веб-приложение для аутентификации.

Я знаю, что отправка хешированного пароля вместо обычного текста не добавляет (много) дополнительной безопасности, поскольку связь возможна только с использованием HTTPS. Однако именно так работают клиенты: им нужна соль для генерации хешированного пароля. Я могу обновить клиентов в будущем, но сейчас это именно то, как работа.

Проблема: Их путь FOSUserBundle хэширует пароль изменился: так как считается, что он НЕ должен указывать соль вручную, но позволяет PHP генерировать соль автоматически (в PHP 7 не возможно даже вручную установить соль), руководство соль больше не поддерживается.

Это не проблема при входе в веб-приложение напрямую, но поскольку клиентам REST по-прежнему нужна соль, это обновление нарушает соединение REST.

Есть ли способ объединить оба метода? Пусть PHP автоматически создает соль, извлекает и отправляет эту соль клиентам?

Насколько я понимаю, соль хранится с хешем в той же строке:

введите описание изображения здесь

Однако просто скопируйте соль 21 char из хэш-строки и отправьте их клиентам не работает. Кажется, что этих 21 символов достаточно для проверки/проверки пароля, но не для повторного создания хэша. Правильно ли это?

Итак, есть ли какое-либо решение использовать PHP password_hash без установки соли и одновременное знакомство с используемой солью?

РЕДАКТИРОВАТЬ 1:

Чтобы ответить на вопрос @RiggsFolly: MD5 не использовался в любое время. Это не правильно, что bcryp/password_hash не будет создавать один и тот же хэш дважды. Он будет делать это, если оба пароля и соль одинаковы:

$s = 'password';
$salt = 'salt5678901234567890123456789012';

$options['salt'] = $salt;
$h1 = password_hash($s,PASSWORD_BCRYPT,$options);
$h2 = password_hash($s,PASSWORD_BCRYPT,$options);

echo $h1 . PHP_EOL;
echo $h2 . PHP_EOL;

Результат:

$2y$10$salt56789012345678901uTWNlUnhu5K/xBrtKYTo7oDy8zMr/csu
$2y$10$salt56789012345678901uTWNlUnhu5K/xBrtKYTo7oDy8zMr/csu

password_hash создаст новый хеш для того же пароля, если соль не указана. Это связано с тем, что соль будет создаваться случайным образом, чем причина разницы в каждом вызове.

ИЗМЕНИТЬ 2:

Как видно в Редактировании 1, использование соли с 32 символами приведет к строке, которая включает только первые 21 символ соли. Однако этот префикс соля не может использоваться для повторного создания одного и того же хэша, поскольку он слишком короткий для принятия.

Однако, если префикс заполнен 0, он, похоже, работает:

$s = 'password';
$salt        = 'salt5678901234567890123456789012';
$salt_prefix = 'salt5678901234567890100000000000';

$h1 = password_hash($s, PASSWORD_BCRYPT, array('salt' => $salt));
$h2 = password_hash($s, PASSWORD_BCRYPT, array('salt' => $salt_prefix));

echo $h1 . PHP_EOL;
echo $h2 . PHP_EOL;

Таким образом, решение может быть:

  • let FOSUserBundle используйте password_hash, чтобы создать хеш без вручную, указав соль.
  • извлеките соль из строки результата и нанесите ее на 0 до 32 символов
  • передать эту соль клиенту

Может ли кто-нибудь подтвердить, что это настоящее решение, а не просто какое-то совпадение?

Ответ 1

Соль есть, как описано на http://us2.php.net/crypt, 22 символа, а не 21.

<?php
$key = 'password';
$hash = password_hash($key, PASSWORD_BCRYPT);
$salt = substr($hash, 7, 22);
$rehash = password_hash($key, PASSWORD_BCRYPT, ['salt' => $salt]);
if ($hash == $rehash) {
  echo 'ok', PHP_EOL;
}

Последние 2 в соль5678901234567890123456789012 соль, меняющаяся на u, - это всего лишь магия в склепной дубинке.

Ответ 2

Позвольте клиенту предоставить соль. Или сервер дает случайную соль, которую он никогда не использовал. Обработайте хэш как сырой пароль. Re-hash хешированный пароль и остальные вещи.