Нужна ли «случайная соль» один раз для пароля или только один раз для базы данных? - PullRequest
31 голосов
/ 08 июня 2010

В дополнение к моему предыдущему вопросу о соленых паролях в PHP / MySQL , у меня есть еще один вопрос, касающийся солей.

Когда кто-то говорит "использовать случайную соль", чтобы предварительно добавить / добавитьпароль, означает ли это:

  • Создание статической случайной строки символов, генерируемой 1 раз , или
  • Созданиестрока символов, которая меняется случайным образом каждый раз при создании пароля ?

Если соль случайна для каждого пользователя и хранится вместе с хешированным паролем, как получается оригинальная соль?назад для проверки?

Ответы [ 4 ]

64 голосов
/ 08 июня 2010

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

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

Затем вы сохраняете результат хеширования.соль и пароль в базе данных hash(salt + password), а также salt для каждого пользователя.Вы можете хранить их в отдельных столбцах или все в одном столбце (разделенных символом, который не используется в хешах, например, ;).Пока вы можете получить оба, все будет в порядке.

Однако, если ваша база данных скомпрометирована, либо из-за того, что кто-то получает локальный доступ, либо с помощью атак с использованием SQL-инъекций, тогда будут доступны как солт, так и финальный хеш, что означает, что атака методом перебора паролей пользователейбыть тривиальнымДля борьбы с этим, как предлагает The Rook , вы также можете использовать секретный ключ, хранящийся в файле локально, в качестве еще одного входа вашего метода хеширования, так что злоумышленнику также необходимо знать это для проведения эффективной атаки.,Это означает, что ваша БД должна быть взломана, а злоумышленнику потребуется доступ к локальным файлам.Таким образом, используя hash(hash(salt + secret) + password) и т. Д.

Хотя в большинстве алгоритмов вы стремитесь максимально ускорить процесс, для хеширования пароля вы хотите замедлить его, это называется Усиление ключа (или иногда Key Stretching).Если для возврата вашей хэш-функции требуется 0,00001 секунды, кто-то может попытаться перебрать 100 000 паролей в секунду, пока не найдет совпадение.Если вашей хэш-функции требуется 1 секунда, чтобы выдать результат, это не имеет большого значения, если кто-то входит в ваше приложение, но для взлома пароля это более сложная задача, поскольку каждая попытка теперь займет 1 секунду, чтобы получитьрезультат, означающий, что для тестирования каждого перебора парольного пароля потребуется в 100 000 раз больше времени, чем при использовании исходной хэш-функции.

Чтобы замедлить вашу хэш-функцию, вам просто нужно запустить ее несколько раз.Например, вы можете сделать new_hash = salt + password + previous_hash 100 000 раз.Вам может потребоваться отрегулировать количество итераций до более высокого значения, если оно слишком быстрое.Если вы хотите изменить значение позже, сохраните количество итераций с пользовательской записью, чтобы не влиять на ранее сохраненные пароли.

Ваша пользовательская запись должна теперь иметь полечто-то вроде «$<algorithm>$<iterations>$<salt>$<hash>» (или, если хотите, в виде отдельных полей).

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

Если пользователь меняет свой пароль, то вы должны сгенерировать новую соль.

Используемый вами метод хеширования не имеет значения (но алгоритм хеширования имеет значение *).Выше я предложил hash(hash(salt + secret) + password), но в равной степени это может быть hash(hash(salt) + hash(secret) + hash(password)).Метод, который вы используете, не меняет эффективность вашего хранилища паролей, один из них на самом деле не более безопасен, чем другой.Полагаясь на то, как вы хэшируете пароль и соль для обеспечения безопасности, это называется безопасность через неизвестность , и ее следует избегать.

* Вы не должны использовать MD5 или SHA-1, так как онисчитаются небезопасными.Вместо этого используйте семейство SHA-2 (SHA256, SHA512 и т. Д.).( Ref )

4 голосов
/ 08 июня 2010

Второй вариант является правильным.

Традиционно соль хранится вместе с хешированным паролем, но не шифруется (обычно предварительно добавляется, , например, в паролях Unix )

Обновление: в большинстве новых систем Unix используется метод этот .

4 голосов
/ 08 июня 2010

Соль должна храниться с хешем для проверки.Лучше всего использовать разную соль при каждом создании или изменении пароля.

2 голосов
/ 08 июня 2010

Динамическое изменение соли намного безопаснее, чем использование единственной статической соли.

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

Конкатенируя соль до конца пароля, затем хэшируйте его, это нормально, но это легко угадываемая формулаЛучше всего придумать свой собственный, то есть сплести соль и пароль, чтобы создать новую строку, а затем хеш, поскольку md5 (пароль + соль) по-прежнему уязвим для атаки по словарю.

...