Перефразировать пароли, не прося всех пользователей их менять
Бывший разработчик использовал 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
из базы данных.
Это работает только при входе пользователей в систему, поэтому у вас будет период времени, когда некоторые пользователи используют старую систему, а некоторые пользователи используют новую.
Я предполагаю, что вы никогда не хранили незашифрованные пароли учетных записей пользователей, поскольку это было бы действительно ужасно. Поэтому у вас больше нет данных, необходимых для создания новых паролей.
Я думаю, что вам нужно, чтобы все обновили свои пароли.