Поддерживать внутреннюю длину пароля единообразной и хранить соль в секрете?

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

Перед хешированием мы убеждаемся, что версия обычного текста всегда содержит 128 символов, обрезая пользовательский ввод до максимум 100, а затем добавляя дополнительные символы в качестве соли.

Таким образом, если пользователь вводит 20 символов, мы добавляем 108 случайных символов в качестве соли. Если пользователь вводит 100, мы добавляем 28 и так далее. Дело в том, что длина текстовой версии должна быть 128 символов. В коде это может выглядеть так:

$salt   = generate_salt($pass); // length varies as explained above
$hash   = hash('sha512', $pass.$salt);

Таким образом, наш «простой текст» перед хешем всегда будет состоять из 128 символов.

Мы храним $hash на сервере A и храним $salt на сервере B.

Теперь давайте предположим, что злоумышленник получает доступ к базе данных хэшей (сервер A) и ему удается реверсировать хэши. Для него это выглядит хорошо, но текстовая версия (или перевернутые хэши), которую он видит, по-прежнему выглядит как хэши, поскольку содержит 128 символов. Поскольку он не знает соли, он никогда не узнает исходный пароль.

В качестве дополнительной проблемы, из-за того, что SHA512 производит 128 символов, он также никогда не будет уверен, что он уже получил текстовую версию, поскольку (как уже упоминалось) текстовая версия выглядит как хэши. На первый взгляд он может подумать, что это итерированная версия, если это так, он, вероятно, будет продолжать итерацию, возможно, до бесконечности.

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

Примечание. Это, конечно, предполагает, что ваше приложение имеет несколько неудачных попыток обнаружения/предотвращения входа в систему.


person IMB    schedule 28.04.2012    source источник
comment
Суть хеша в том, что его нельзя отменить.   -  person zimdanen    schedule 30.04.2012
comment
@zimdanen Согласен, но это обратимо с помощью радужных/словарных атак.   -  person IMB    schedule 30.04.2012
comment
Вот почему вам нужна соль, но, как вы и ответы упомянули, соль не нужно хранить в секрете. Сам хэш будет держать данные в секрете; соль только усложняет вычисление радужных таблиц.   -  person zimdanen    schedule 30.04.2012
comment
@zimdanen Вы правы, но я думаю, вы согласитесь, что если соль была спрятана, вы еще больше продлите агонию хакера. В противном случае, если бы он знал соль, его испытания теперь на шаг впереди.   -  person IMB    schedule 30.04.2012
comment
Это все игра, в которой злоумышленнику становится все труднее и труднее. Однако я думаю, что в системе, вероятно, есть и другие проблемы, которые заслуживают большего внимания. Например, вероятно, лучше сосредоточиться на том, чтобы злоумышленник не попал в систему. ;)   -  person zimdanen    schedule 30.04.2012


Ответы (3)


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

Используйте существующий (например, PBKDF2, bcrypt или scrypt), которые имеют преимущества перед простыми хэшами с солью, поскольку они используют больше процессорного времени (все три) и/или памяти. (последние два), что делает распараллеливание дорогим.

Соль в хэше защищает только от радужных таблиц, а не от брутфорса!.

Если злоумышленнику удастся обратить хэши, он узнает $pass.$salt (и, следовательно, пароль).

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

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

На практике, однако, он, вероятно, сможет получить доступ к серверу B, как только он получит доступ к серверу A.

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

Кстати, SHA-512 выдает 512 бит, что составляет 64 символа ASCII.

person Dennis    schedule 28.04.2012
comment
Я ничего не изобретаю, в этом примере используется SHA512. Я просто добавляю реализацию более высокого уровня поверх него. Базовый криптохеш в этом примере — SHA512, что означает, что я могу заменить его на bcrypt и т. д. - person IMB; 29.04.2012
comment
Он получает $pass.$salt, но система усекает/добавляет случайные символы в исходный проход, навсегда скрывая исходный проход. Он также не знает, что такое соль, поэтому ему сложнее понять, где начинается соль. - person IMB; 29.04.2012
comment
Этот пример предполагает, даже если всякая надежда потеряна, т.е. вся система была скомпрометирована. Злоумышленник никогда не узнает исходные пароли, поскольку исходные пароли были усечены/добавлены и, следовательно, бесполезны при попытке использовать их в других системах, таких как Facebook/Банковское дело/Электронная почта/и т. д. - person IMB; 29.04.2012
comment
SHA512, по крайней мере, в PHP выдает 128 символов. - person IMB; 29.04.2012
comment
Я ничего не изобретаю Все ваши идеи относительно заполнения переменной длины и т. д. являются новой криптосистемой. bcrypt специально разработан для паролей, поэтому вам не нужно беспокоиться о добавлении соли и т. д., вы просто используете его. навсегда скрыть исходный пароль Знание $pass.$salt означает, что злоумышленнику остается только угадать длину пароля. Это занимает около 50 попыток, и он готов! вся система была скомпрометирована Если сервер A может запросить пароли с сервера B, а сервер A скомпрометирован, нет оснований предполагать, что сервер B не будет. - person Dennis; 29.04.2012
comment
SHA512, по крайней мере, в PHP выдает 128 символов. Да, но шестнадцатеричные символы (цифры или буквы от A до F). - person Dennis; 29.04.2012

Первая проблема с этим подходом заключается в том, что вы реализуете свой собственный криптографический код. Это почти всегда плохая идея; Crypto сложна, и ее очень легко испортить тонкими способами, и другие люди вложили много времени и усилий в реализацию криптографических примитивов и сервисов, построенных поверх них, чтобы вам не пришлось этого делать. Но давайте предположим ради аргумента, что вам действительно нужно это сделать :-).

Во-вторых, вы усекаете пользовательский ввод — выбрасываете драгоценную энтропию — без какой-либо пользы. Вы готовы генерировать до 128 символов соли; почему бы просто не делать это всегда и не добавлять их (вместе с паролем) в свой хэш? Что вы получаете, усекая? Единственный ответ, который я вижу, заключается в том, что якобы исходные пароли «выглядят как хэши, поскольку они состоят из 128 символов», но это просто неправда; ваши соленые пароли по-прежнему начинаются с фактических данных пароля, которые обычно очень сильно отличаются от хэшей.

В-третьих, что может быть просто моей неспособностью правильно прочитать ваши мысли, это то, что непонятно, откуда берутся эти ваши соли. Вы описываете их как «случайные» и говорите, что злоумышленники их не узнают; но тогда как ваша система аутентификации получает их? Кажется, что они получены из пароля, но в этом случае добавление соли и хэширование — это просто немного более сложная хэш-функция, и вы ничего не выиграли.

Общий принцип, который вы, по-видимому, отвергли (или, возможно, не встретили), заключается в следующем: Всегда разрабатывайте криптографические системы, исходя из предположения, что злоумышленники знают все, что они могут знать, включая весь ваш исходный код. Это хороший принцип, и вы не должны отвергать его. Полагаться на небольшой «дополнительный уровень запутывания» не сослужит вам хорошую службу; в худшем случае это сделает ошибки более вероятными (за счет усложнения системы) и вызовет чувство ложной безопасности.

person Gareth McCaughan    schedule 28.04.2012
comment
Во-первых, я не реализую свой собственный криптографический код, в примере используется SHA512. - person IMB; 29.04.2012
comment
Во-вторых, целью было усечение, а затем добавление случайных данных (что добавляет пользовательскую энтропию), тем самым изменяя фактический пароль. Поскольку исходный пароль пользователя был усечен/добавлен, он не будет работать с Facebook, если пользователь использует для него тот же пароль. В-третьих, соли генерируются и сохраняются на сервере B. Для аутентификации приложение усекает ввод, получает соль с сервера B и сравнивает хэш. - person IMB; 29.04.2012
comment
Я согласен с общим принципом, но в этом примере предполагается, что скомпрометированы только хеш-таблицы. Если действительно вся система была скомпрометирована, то обратные хэш-таблицы бесполезны, поскольку злоумышленник в основном получил всю необходимую ему информацию. В этом примере предполагается, что в случае перестановки хеш-таблиц исходный пароль пользователя никогда не будет раскрыт, поскольку система усекла/добавила его. Единственный шанс, что злоумышленник сможет полностью восстановить исходный пароль, — это украсть всю систему, включая сервер A, сервер B и коды приложений. - person IMB; 29.04.2012
comment
IMB, вы внедряете свой собственный криптографический код, даже если используете SHA512 в качестве примитива. Важны, тонки и очень легко ошибиться не только примитивы самого низкого уровня. Во-вторых, добавление без усечения дает все упомянутые вами преимущества от усечения без затрат. В-третьих, если B скомпрометирован, то все соли известны, и в любом случае, если A или B скомпрометированы, то на практике, вероятно, также скомпрометированы и другие соли. В-четвертых, исходный пароль не нужен, потому что система использует только его бит после усечения. - person Gareth McCaughan; 29.04.2012
comment
Что правда, так это то, что если вы урежете пароли для этой системы и действительно выбросите то, что вы отрубили, то данные, восстановленные из системы, будут менее полезны для компрометации других систем. На практике я сомневаюсь в полезности этого, не в последнюю очередь потому, что пользователь, чьи пароли фактически изменены путем усечения до 100 символов, скорее всего, в любом случае не использует тот же пароль для вашей системы, что и для Facebook. - person Gareth McCaughan; 29.04.2012

Salt не обязательно должен быть секретным, его единственная цель — сохранить уникальность всего хэша

Это также делает «медленнее» перебор таблицы хэшей, поскольку вам нужна попытка для каждой строки для каждой комбинации хэш + соль вместо того, чтобы просто попробовать один хеш для всей таблицы («выбрать * из паролей, где хеш =» ххх'')

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

Тот факт, что ваши «обратные хэши» выглядят как хэши, не добавляет реальной дополнительной безопасности (на самом деле это просто безопасность за счет неизвестности). Ваш веб-сервер должен будет подключиться к серверу A и серверу B (для аутентификации комбинации пользователя и пароля), поэтому, когда этот сервер будет скомпрометирован, всякая надежда будет потеряна.

Вас может заинтересовать эта запись в блоге Джеффа Этвуда. . (изменить: размещена неправильная ссылка codinghorror)

person ChristopheD    schedule 28.04.2012
comment
Я согласен с тем, что весь смысл в замедлении реверсирования хэша, и я считаю, что добавление безопасности за счет неясности добавляет дополнительный уровень медлительности поверх исходного криптографического хэша. Смысл здесь в том, чтобы у нападавшего болела голова на протяжении всего его испытания. - person IMB; 29.04.2012
comment
Всякую надежду не так легко потерять, поскольку злоумышленнику приходится пройти через несколько стен: 1. Взломать сервер А. 2. Взломать сервер Б. 3. Взломать код приложения. 4. Переверните хэши. 5. Выясните связь между солью и хешем. 6. Если он обнаружит, что код приложения усекает/добавляет кучу случайных символов, он в конце концов поймет, что никогда не узнает исходный пароль пользователя. Теперь я не уверен в других, но этот процесс совершенно медленный. - person IMB; 29.04.2012