У меня есть сайт LAMP (PHP), который становится популярным.
Я играл в нее безопасно, сохраняя пароли пользователей в виде хешей md5.
Но теперь я вижу, что это не безопасно; Я должен был солить хеш md5 – потому что в настоящее время можно декодировать несоленые хеши md5 с использованием радужных таблиц.
Что я могу сделать?
Я не хочу, чтобы каждый вводил новый пароль.
Вы можете сделать «двухэтапное хеширование» вместо создания хеша за один шаг.
Вы можете добавить хэш пароля к имени пользователя, а затем снова добавить его. Это создаст неразрешимый хеш, который будет солен с уникальной информацией.
Обычный процесс соления
соль + PWD -> хэш
Вы можете сделать что-то вроде: PWD -> Hash -> UserID + Hash -> Hash
(Обратите внимание, что UserID выбрана так, чтобы была уникальная соль для каждого двойного хэша … Не стесняйтесь сделать соль более сложной)
Вы можете солить их на лету. Добавьте фрагмент кода, чтобы при входе в систему он выполнял обычный процесс (вычисляет сумму MD5 пароля и проверяет ее на сохраненный хеш), и если это удастся, перекомпилируйте соленую версию хэша из файла clear- текстовый пароль, который они ввели, и сохраните его в файле паролей.
Единственная морщина заключается в том, что вам нужно будет добавить индикатор того, будет ли каждый MD5 солен или нет, так как у вас будет смесь обоих на некоторое время. Или, для незначительной потери безопасности, вы можете проверить каждый соленый и несоленый пароль, и если один из них ударит, примите логин. Конечно, если вы обнаружите, что он был несоленым, тогда вы обновляетесь в этот момент.
Ответ прост, убедитесь, что у вас есть запись или какой-то флаг, у которого у пользователей есть пароли в новой системе хеширования, когда они следуют логину, аутентифицируют их, вычисляют новый хеш, переворачивают флаг.
Теперь, когда кто-то входит в систему и установлен флаг, выполните аутентификацию с помощью нового хэша.
Почему бы не добавить новый столбец new_pwd
в свою пользовательскую таблицу, в которой хранится результат md5($originallyHashOfPwd . $salt)
new_pwd
md5($originallyHashOfPwd . $salt)
. Затем вы можете предварительно new_pwd
и как только это будет выполнено, скорректируйте свою проверку входа, чтобы сравнить результат md5(md5($entered_pwd) . $salt)
с тем, что находится в new_pwd
. Как только вы закончите переключение проверки входа в систему, удалите старый столбец.
Это должно прекратить атаки стиля радужного стола.
Вы все еще можете использовать соль. Просто вычислите другой хеш из текущего хэша вместе с солью:
$newHash = md5($salt.$oldHash);
Для новых паролей вам необходимо использовать:
$hash = md5($salt.md5($password));
Отличный способ обновить пароли, а также сделать их более безопасными – это перейти на использование соленых SHA1 для паролей. SHA1 сложнее создать столкновение против, и он также имеет другую длину строки для MD5. MD5 имеет длину 32 символа, а SHA1 – 40 символов.
Чтобы преобразовать их в PHP, сначала проверьте длину строки хранимого пароля. Если это 32 символа, проверьте пароль, используя старый метод, а затем напишите новый, используя SHA1 в базе данных.
Если я правильно помню, именно так WordPress справился с этой проблемой.
Динамически повторно зашифровывать пароли, когда пользователи регистрируются в следующий раз, то есть сначала проверяют, правильно ли это, затем зашифруйте его солью и сохраните снова.
Вы можете перенести пароли, добавив столбец в свои таблицы, чтобы сохранить новый формат.
Когда пользователь успешно войдет в систему, если новый столбец пуст, поместите там более сильный пароль и выпустите исходный столбец. Если в новом столбце есть запись, сравните вход с этим значением.
Здесь есть два варианта
Насколько я вижу, нет другого способа восстановить пароли.
EDIT: хотя MD5 является хешем и не должен быть декодируемым, его можно сломать с использованием таблиц радуги: с вероятностью почти один вы можете найти уникальную строку (здесь есть вероятность) максимум, скажем, 20 символов с заданным хешем, особенно если ваш набор символов ограничен, скажем, буквенно-цифровым. Строго говоря, это не декодирование. Для всех практических целей это так. Дополнительное примечание: создание радужных столов, а поиск 1000 паролей по-прежнему займет много времени.
Соль оригинального хэша, как упоминалось другими. Всего несколько указателей здесь:
Если вы отодвигаетесь от MD5, вам следует пропустить просто соление и перейти к еще лучшей технике, называемой растяжкой. В частности, вы должны использовать bcrypt (реализованный как PHPASS с php).
Вот отличная ссылка на почему bcrypt: http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s .html
И вот краткое описание: 1. Загрузите пакет phpass: http://www.openwall.com/phpass/ 2. Посмотрите на test.php для примеров, подобных приведенным ниже:
require 'PasswordHash.php'; $t_hasher = new PasswordHash(8, FALSE); $correct = 'plaintextpassword'; $hash = $t_hasher->HashPassword($correct); $check = $t_hasher->CheckPassword($correct, $hash);
Если $ check === true (что выше), то пароль правильный. Если ваш пароль «привет», вы можете использовать его с помощью HashPassword, помещать хэш в базу данных, а когда пользователь входит в систему, вызовите CheckPassword (userenteredpassword, hashInDb), чтобы узнать, правильно ли пароль
к сожалению, ваш единственный способ – сообщить своим пользователям обновить свои пароли.
вы также можете генерировать случайные пароли, но это одна и та же проблема.
редактировать
вы можете просто закодировать сохраненные пароли. поэтому ваш новый алгоритм хеширования соленой будет:
md5(md5($new_password).$salt).':'.$salt
для обновления ваших старых паролей
md5($old_password.$salt).':'.$salt
чтобы проверить, правильно ли предоставлен пароль, просто используйте
list($stored_password, $salt) = explode(':', $salted_password); if(md5(md5($provided_password).$salt) == $stored_password) { // you are now logged in }