Пароли и разные виды шифрования - PullRequest
2 голосов
/ 09 ноября 2010

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

В настоящее время я работаю над веб-сайтом, который должен быть запущен по всей моей стране, поэтому ему нужна какая-то защита для пользовательской системы.

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

Один говорит, что для пароля достаточно простого шифрования SHA512, другие говорят, что вы должны использовать «соль», что бы вы ни делали, и есть парни, которые говорят , что вы должны построить совершенно новую машину для шифрования пароля, потому что таким образом никто не сможет получить его .

Пока я использую hash_hmac(); с SHA512, плюс, пароль получает случайную соль SHA1 и последнюю часть, определенную случайным образом md5 (); ключ. Для большинства из нас это будет звучать безопасно, но так ли это?
Я недавно читал здесь на SO, что bcrypt(); (теперь известный как crypt(); с хешированием Blowfish) является наиболее безопасным способом. После прочтения руководства по PHP о crypt(); и связанных с ним вещах я запутался.

По сути, вопрос в том, удастся ли мне hash_hmac(); одолеть Удар crypt(); или наоборот?

И еще, может быть, есть более безопасные варианты хеширования пароля?

Ответы [ 3 ]

10 голосов
/ 09 ноября 2010

Ключ к правильному применению криптографии - определить с достаточной точностью, какие свойства вы ищете.

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

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

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

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

  1. взломать один пароль должно быть сложно (считанные дни или недели, а не секунды);
  2. взломать два пароля должны быть вдвое такими же сложными, как взломать один.

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

1. Медленный хэш

Хэш-функции работают быстро. Вычислительная мощность дешева. В качестве точки данных, с SHA-1 в качестве хэш-функции и графической картой NVidia за 130 $, я могу хэшировать 160 миллионов паролей в секунду. Стоимость 2 31 оплачивается примерно за 13 секунд. Таким образом, SHA-1 слишком быстр для безопасности.

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

Например, если дана хеш-функция H , используйте другую хеш-функцию H ', определенную как:

H '(x) = H (x || x || x || ... || x)

где ' || ' означает конкатенацию. Проще говоря, повторите ввод достаточно много раз, чтобы вычисление функции H ' заняло некоторое незначительное время. Таким образом, вы устанавливаете цель времени, например, 1 мс, и настройте количество повторений, необходимое для достижения этой цели. 10 мс означает, что ваш сервер сможет аутентифицировать 10 пользователей в секунду, затратив всего 10% его вычислительной мощности. Обратите внимание, что речь идет о сервере, хранящем хешированный пароль для собственного скрытого использования, поэтому здесь нет проблемы взаимодействия: каждый сервер может использовать определенное количество повторений, специально разработанное для его мощности.

Предположим теперь, что злоумышленник может в 100 раз увеличить вашу вычислительную мощность; например злоумышленник - скучающий студент - заклятый враг многих систем безопасности - и может использовать десятки компьютеров в своем университетском городке. Также злоумышленник может использовать более тщательно оптимизированную реализацию хэш-функции H (вы говорите о PHP, но злоумышленник может выполнить сборку). Более того, злоумышленник - пациент : пользователи не могут ждать более доли секунды, но достаточно скучающий студент может попробовать несколько дней. Тем не менее, попытка 2 миллиардов паролей все еще потребует около 3 полных дней вычислений. Это не совсем безопасно, но намного лучше, чем 13 секунд на одном дешевом ПК.

2. Соли

A salt - это часть общедоступных данных, которую вы хэшируете с паролем для предотвращения общего доступа .

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

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

Соль должна использоваться для проверки пароля, поэтому сервер должен хранить для каждого хешированного пароля значение соли, которое использовалось для хеширования этого пароля. В базе данных это просто дополнительный столбец. Или вы можете объединить соль и хеш-пароль в одном двоичном объекте; это только вопрос кодирования данных, и это зависит от вас.

Предполагая, что S является солью (т.е. несколько байтов), процесс хеширования для пароля p равен: H '(S || p) ( с функцией H ', определенной в предыдущем разделе). Вот и все!

Соль в том, чтобы быть, насколько это возможно, уникальным для каждого хешированного пароля. Простой способ добиться этого - использовать случайные соли : всякий раз, когда пароль создается или изменяется, используйте генератор случайных чисел, чтобы получить 16 случайных байтов. 16 байтов должно быть достаточно, чтобы сделать повторное использование соли маловероятным. Обратите внимание, что соль должна быть уникальной для каждого пароля : использование имени пользователя в качестве соли недостаточно (некоторые отдельные экземпляры сервера могут иметь пользователей с одинаковым именем - сколько существует "bob") ? - а также, некоторые пользователи меняют свой пароль, и новый пароль не должен использовать ту же соль, что и предыдущий пароль).

3. Выбор хеш-функции

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

Наиболее часто используемые хэш-функции: MD5, SHA-1, SHA-256, SHA-512 (последние две известны под общим названием "SHA-2"). Некоторые недостатки были обнаружены в MD5 и SHA-1. Эти слабые стороны оказывают серьезное влияние на некоторые использования, но не для того, что описано выше (слабые стороны касаются столкновений, тогда как мы работаем здесь над сопротивлением прообразу). Тем не менее, по связям с общественностью лучше выбрать SHA-256 или SHA-512: если вы используете MD5 или SHA-1, вам, возможно, придется оправдываться. SHA-256 и SHA-512 отличаются размером выходных данных и производительностью (в некоторых системах SHA-256 намного быстрее, чем SHA-512, а в других SHA-512 быстрее, чем SHA-256). Однако производительность здесь не является проблемой (независимо от внутренней скорости хэш-функции, мы делаем ее намного медленнее за счет повторений ввода), и 256 битов вывода SHA-256 более чем достаточно. Усечение вывода хеш-функции до первых n битов, чтобы сэкономить на хранении, является криптографически допустимым, если вы сохраняете не менее 128 бит ( n> = 128 ) .

4. Заключение

Всякий раз, когда вы создаете или изменяете пароль, генерируйте новую случайную соль S (16 байт). Затем хэшируйте пароль p как SHA-256 (S || p || S || p || S || p || ... || S || p) где шаблон ' S || p ' повторяется достаточно много раз, чтобы процесс хеширования занимал 10 мс. Сохраните S и результат хеширования. Чтобы проверить пароль пользователя, получите S , пересчитайте хэш и сравните его с сохраненным значением.

И ты будешь жить дольше и счастливее.

2 голосов
/ 09 ноября 2010

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

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

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

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

Я не самый квалифицированный специалист, чтобы комментировать выбор алгоритма, поэтому я оставлю это кому-то еще.

1 голос
/ 09 ноября 2010

Я не разработчик PHP, но у меня есть некоторый опыт работы с шифрованием.Моя первая рекомендация, как предложил Crippledsmurf, абсолютно не пытаться «свернуть свое» шифрование.На нем будет написано бедствие.

Вы говорите, что используете hash_hmac() в настоящее время.Если вы просто защищаете учетные записи пользователей и некоторую основную информацию (имя, адрес, адрес электронной почты и т. Д.), А не что-то важное, например, SSN, кредитные карты, я думаю, что вы можете безопасно использовать то, что у вас есть.* С помощью шифрования нам всем хотелось бы самое безопасное и сложное хранилище для защиты наших вещей, но вопрос в том, зачем иметь огромную безопасную дверь для защиты вещей, которые никто не хотел бы реально хотеть?Вы должны сбалансировать тип и силу используемого вами шифрования с тем, что вы защищаете, и риском его использования.

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

Позвоните - стоит ли защищать дальше.Если нет, не тратьте свое время и двигайтесь дальше.

...