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

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

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

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

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

В вашем 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 <5.5) https://github.com/ircmaxell/password_compat/ , важно отметить, что если длина вашего текущего столбца пароля меньше, чем 60, его необходимо будет изменить на это (или выше). В руководстве предлагается длина 255.

Вам потребуется ALTER length вашей колонки и начать с нового хеша, чтобы он вступил в силу. В противном случае MySQL будет терпеть неудачу.

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

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

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

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

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

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

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

 if(hash_equals($pass_hash_from_db, crypt($user_input, '$1$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 .