Перефразировать пароли, не прося всех пользователей их менять

Бывший разработчик использовал PHP hash() функция с алгоритмом SHA256 для хранения хэшей паролей. Чтобы повысить безопасность системы, я хотел бы начать использовать crypt() с алгоритмом Blowfish (к сожалению, у нас нет PHP 5.5 и, следовательно, password_hash() не доступен).

Поскольку SHA256 является необратимым алгоритмом хеширования, есть ли способ начать использовать crypt() с солеными паролями, не прося всех сбросить свой пароль?

7 ответов

Решение

Тогда вы должны использовать библиотеку совместимости. Это облегчит вам переход на 5.5.

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

if (password_verify($password, $hash)) {
    // Matches...
} elseif (hash('sha256', $password) == $hash) {
    // Matches...
    $newHash = password_hash($password);
    // Save $newHash in the old hash's place
} else {
    die('Invalid password...');
}

Технически возможно взломать много хэшей, но с этим слишком много проблем (вы не получите все из них, это, скорее всего, неосуществимо, возможно, даже не законно и т. Д.).

Другим подходом, который вы можете рассмотреть, является создание цепочки хеширования: поскольку вы не можете изменить SHA256, просто определите вашу новую хеш-функцию как crypt(sha256($passwd)), Поскольку у вас уже есть sha256($passwd) в файле для всех ваших паролей, можно crypt() каждый из них с соответствующей солью для обновления существующих хешей (без необходимости ждать входа пользователя).

Вот возможное решение:

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

Это предполагает, что вы передаете свободные текстовые пароли через Интернет, чего не следует делать, если вы не используете SSL.

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

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

Я бы сказал, используйте поле маркера, чтобы аннотировать, какие пользователи ранее хэшировали, а затем шифровать существующий хеш. Для тех, кто имеет значение true в поле маркера, когда аутентификация становится двухэтапным процессом, хешируйте пароль, а затем шифруйте его для проверки соответствия.

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

Могут быть и другие более быстрые и эффективные способы сделать это, но если вы хотите сделать это, не затрагивая ваших пользователей, я бы так и сделал -

Добавьте еще один столбец к вашей таблице, базовый флаг, который может иметь значение True или False. По умолчанию это false. Затем реализуйте следующий псевдокод:

if(flag=true)
{
 use crypt() and authenticate user
}
else
{
use hash() and authenticate user
use crypt() on the provided password (once authenticated)
update the record to put the new password into the table
set flag=true
}

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

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

Да, вам нужно добавить дополнительный столбец, в котором хранятся crypt() выход. Когда пользователь входит в систему, и его пароль успешно hash()es к тому, что у вас есть в базе данных, теперь можно crypt() этот пароль, и удалите старый hash из базы данных.

Это работает только при входе пользователей в систему, поэтому у вас будет период времени, когда некоторые пользователи используют старую систему, а некоторые пользователи используют новую.

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

Я думаю, что вам нужно, чтобы все обновили свои пароли.

Другие вопросы по тегам