Преобразование хэшей паролей md5 в хэш паролей PHP 5.5()

новый API password_hash в PHP 5.5 хорош, и я хотел бы начать использовать его везде. Учитывая более старый проект со старой базой данных, где пароли хранятся в хэшах md5, каков наилучший способ переноса старых паролей пользователей в новый, более безопасный API?

помимо простого запроса пользователям сбросить свой пароль при следующем входе в систему (это непрактично и раздражает пользователей), я думал о возможности использования текущего хэша md5 в качестве входа в функция password_hash() для всех существующих пользователей. Чтобы проверить пароли для этих пользователей (во время входа в систему), я бы преобразовал их ввод в хэш md5, а затем использовал его для password_verify (). Новые пользователи будут избавлены от этого дополнительного шага.

стоит ли так поступать? Есть ли лучшие способы прозрачной миграции, в которых пользователи не ворчат о сбросах паролей, но я могу сразу же воспользоваться преимуществами более безопасного хэширования?

самое главное, есть даже преимущество безопасности в принятии существующих хэшей md5 (которые склонны к грубой силе) и использовании API password_hash () для "двойного хэша"?

3 ответов


в своем login.php (?) вы конвертируете старые пароли из MD5 в bcrypt и заменяете старый хэш MD5 в базе данных новым.

псевдо код:

$password = $_POST["password"];

if (substr($pwInDatabase, 0, 1) == "$")
{
    // Password already converted, verify using password_verify
}
else
{
    // User still using the old MD5, update it!

    if (md5($password) == $pwInDatabase)
    {
        $db->storePw(password_hash($password));
    }
}

двойное хеширование не повысит безопасность bcrypt, так как bcrypt itsef является односторонней функцией хеширования.

Nota: MD5 создает строку длиной 32 символа, в то время как password_hash() минимум 60.

читать инструкцию:

если и когда вы решите использовать password_hash() или пакет совместимости (если PHP https://github.com/ircmaxell/password_compat/, важно отметить, что если длина вашего текущего столбца пароля меньше 60, его нужно будет изменить на это (или выше). Руководство предлагает длину 255.

вы вам нужно будет изменить длину вашего столбца и начать с нового хэша, чтобы он вступил в силу. В противном случае MySQL будет прекращена.


поскольку это один из способов шифрования, если вы не хотите пароли пользователей на странице входа в систему, которая не является безопасной, вы можете заставить пользователей повторно ввести свои пароли. Другой вариант-повторно зашифровать все записи базы данных с помощью password_hash() на md5() хэшированные пароли и сохраните эти значения в базе данных, затем на Вашей странице входа в PHP поместите password_hash() вокруг md5(), что-то вроде:

password_hash(md5($_POST['password']));

используя второй путь вы не должны иметь потребителя переустановить их пароли.


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

в этом случае хэширование пароля при регистрации / изменении пароля будет выглядеть так:

$pass_hash = crypt($pass, '$salthere');
// store $pass_hash in database

и тогда у вас будет сравнение с:

if(hash_equals($pass_hash_from_db, crypt($user_input, '$salthere')))
{
  // user logged in
}

красота этого перехода заключается в том, что ваша база данных уже будет готова к использованию password_verify.

Регистрация / изменение пароля станет:

 $pass_hash = password_hash($pass);
 // store $pass_hash in database

и вы замените сравнение с:

if(password_verify($user_input, $pass_hash_from_db))
{
  // user logged in
}

это просто сработает из коробки и обновит все пароли пользователя при следующем изменении пароля. Но нам не нужно ждать и делать то, что @Fabian сделал в своем ответе здесь.

здесь нам нужно только изменить логин:

if(password_verify($user_input, $pass_hash_from_db))
{
  // user logged in
  if(password_needs_rehash($pass_hash_from_db, PASSWORD_DEFAULT))
  {
    $pass_hash = password_hash($user_input);
    // store $pass_hash in database
  }
}

это послужило бы дополнительным преимуществом обновления паролей пользователя как как только новый алгоритм пароля станет алгоритмом PHP по умолчанию. На самом деле вам ничего не придется делать.

если вы хотите использовать дополнительные параметры для функции хэширования пароля (например, изменить "стоимость"), вы должны посмотреть функция password_hash и функции password_needs_rehash документация, обратите внимание на дополнительный последний параметр $options .