Безопасное хранение соли

Что более безопасно и чем:

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

Ответы (2 шт):

Автор решения: AivanF.

Рассмотрим варианты детальнее

Вариант 1. Хранить одну общую соль для всех паролей пользователей вне БД

hash(secret + password)

С виду это выглядит безопаснее, ведь если кто-то получит доступ до БД, то соли у него не будет, и наверное восстановить пароли не сможет?..

Но если злоумышленник получит доступ и к БД, и к соли из переменной среды, то для извлечения паролей всё равно надо будет строить радужную таблицу. И если у вас одна соль на всех юзверей, то это гораздо сделать проще. Другая проблема с безопасностью: если злоумышленник (или его соучастник/жертва) имеет доступ к системе как пользователь, то он уже знает 1 пароль и его хэш, возможно сможет менять пароль и смотреть изменения хэша, находить в БД других пользователей с таким же паролем...

Этот вариант похож на принцип Security through obscurity (безопасность через неясность/запутывание), а этого принципа советуют избегать и полагаться на более сильные криптографические методы.

Вариант 2. Хранить свою для каждого пользователя соль в БД с хэшами паролей

hash(salt + password)

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

Этот же способ используется в Django, также его советуют и обосновывают в аналогичном вопросе на enSO – советую почитать, там обсуждены разные варианты и их обоснования.


Как упомянули в комментариях, вопрос на самом деле спорный и зависит от реализации вашей системы. Если у вас лишь 1 или несколько серверов с полным или слабо защищённым доступом друг до друга, то скорее всего злоумышленник получивший доступ к БД, легко получит доступ и к ОС с переменными окружения, и наоборот, что нивелирует смысл первого варианта. Если же у вас большая и продуманная инфраструктура, доступы к БД и серверам с кодом разграничены, настроены жёсткие группы безопасности, везде используются юзеры с ограничениями и в БД, и в ОС везде, то можно поиметь выгоду с первого способа. Поэтому есть следующий вариант.

Вариант 3. Смешать оба варианта

Можно совместить лучшее от двух миров, например так:

hash(hash(salt + secret) + password)

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

→ Ссылка
Автор решения: Barmaley

Ни то ни другое.

  1. Для каждого юзера своя соль - очевидность этого даже не требует доказательств, если будет 1 соль, то под эту соль для всех юзеров генерируется 1 радужная таблица, что существенно облегчает задачу атакующего
  2. Соль необходимо хранить отдельно от хэшей. Желательно даже в разных БД, ну или хотя бы в разных таблицах.
  3. Поскольку соль по своей природе открыта, то желательно озаботиться перцем (pepper), который в отличие от соли надо хранить в секрете: key = hash(password+pepper+salt)
→ Ссылка