Переход от несоленых к соленым паролям MD5

У меня есть сайт 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 справился с этой проблемой.

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

Вы можете перенести пароли, добавив столбец в свои таблицы, чтобы сохранить новый формат.

Когда пользователь успешно войдет в систему, если новый столбец пуст, поместите там более сильный пароль и выпустите исходный столбец. Если в новом столбце есть запись, сравните вход с этим значением.

Здесь есть два варианта

  • Дешифруйте сами пароли и перекодируйте их с солью (я рекомендую что-то более интересное, чем MD5). Вы должны сообщить пользователям, что вы просматриваете свои пароли незашифрованными. Это, вероятно, займет много времени.
  • Заставьте их перепечатать свои пароли и сохранить их соленые и зашифрованные.

Насколько я вижу, нет другого способа восстановить пароли.

EDIT: хотя MD5 является хешем и не должен быть декодируемым, его можно сломать с использованием таблиц радуги: с вероятностью почти один вы можете найти уникальную строку (здесь есть вероятность) максимум, скажем, 20 символов с заданным хешем, особенно если ваш набор символов ограничен, скажем, буквенно-цифровым. Строго говоря, это не декодирование. Для всех практических целей это так. Дополнительное примечание: создание радужных столов, а поиск 1000 паролей по-прежнему займет много времени.

Соль оригинального хэша, как упоминалось другими. Всего несколько указателей здесь:

  • Соли лучше, чем дольше они. Также, если они содержат больше, чем просто [a-z0-9], но длина лучше в первую очередь.
  • Если у кого-то уже есть копия вашей БД и вы переиздаете одни и те же пароли с солью, перефразировать старый хэш с солью не получится. Вместо этого вы действительно должны заставить пользователей создать новый пароль.
  • Вы должны сопоставлять новые пароли (и пароли для соления) с различными списками наиболее часто используемых паролей. Они используются в атаках «грубой силы». Запросить / заставить пользователя сменить пароль.

Если вы отодвигаетесь от 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 }