Безопасный хеш и соль для паролей PHP

В настоящее время говорят, что MD5 частично небезопасен. Учитывая это, я хотел бы знать, какой механизм использовать для защиты паролем.

Этот вопрос, является ли «двойное хеширование» паролем менее безопасным, чем однократное хеширование? предполагает, что хэширование несколько раз может быть хорошей идеей, тогда как как реализовать защиту паролем для отдельных файлов? предлагает использовать соль.

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

  1. Механизм хеширования должен быть доступен в PHP
  2. Это должно быть безопасно
  3. Он может использовать соль (в этом случае все соли одинаково хороши? Есть ли способ получить хорошие соли?)

Кроме того, я должен хранить два поля в базе данных (например, одно с использованием MD5, а другое с использованием SHA)? Будет ли это сделать это безопаснее или небезопаснее?

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

Связанные вопросы, которые не совсем охватывают мой вопрос:

В чем разница между SHA и MD5 в PHP
Простое шифрование паролей
Безопасные методы хранения ключей, паролей для asp.net
Как бы вы реализовали соленые пароли в Tomcat 5.5

30.12.2008 22:02:45
openwall.com/phpass также очень хорошая библиотека
Alfred 2.07.2011 01:02:57
Md5 теперь совершенно небезопасен
JqueryToAddNumbers 6.07.2012 05:14:54
@NSAwesomeGuy Это зависит от того, для чего вы его используете. Конечно, несложно сопоставить или просто перебрать несоленые пароли MD5, но с приличным подсолом все еще крайне непрактично создавать радужный стол для быстрого взлома наборов паролей, а перебор - бесполезен.
Craig Ringer 24.08.2012 06:54:53
В PHP 5.5+ есть встроенный в php.net/manual/en/function.password-hash.php
Terence Johnson 1.01.2013 16:09:04
hakre 27.06.2013 00:58:47
14 ОТВЕТОВ
РЕШЕНИЕ

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ : Этот ответ был написан в 2008 году.

С тех пор PHP дал нам password_hashи password_verify, с момента их появления, они являются рекомендуемым методом хеширования и проверки пароля.

Теория ответа все еще хорошо читается.

TL; DR

Этикет

  • Не ограничивайте количество символов, которые пользователи могут вводить для паролей. Только идиоты делают это.
  • Не ограничивайте длину пароля. Если ваши пользователи хотят получить предложение с суперкалифрагистическим выражением, не запрещающее им использовать его.
  • Не удаляйте HTML-код и специальные символы в пароле.
  • Никогда не храните пароль своего пользователя в виде обычного текста.
  • Никогда не отправляйте пароль пользователю по электронной почте, за исключением случаев, когда он потерял свой, и вы отправили временный пароль .
  • Никогда, никогда не регистрируйте пароли каким-либо образом.
  • Никогда не хэшируйте пароли с SHA1 или MD5 или даже с SHA256! Современные взломщики могут превышать 60 и 180 миллиардов хэшей в секунду (соответственно).
  • Не смешивайте bcrypt и с необработанным выводом hash () , либо используйте шестнадцатеричный вывод, либо base64_encode. (Это относится к любому вкладу, который может содержать мошенника \0, что может серьезно ослабить безопасность.)

ДОС

  • Используйте Scrypt, когда можете; bcrypt если не можешь.
  • Используйте PBKDF2, если вы не можете использовать ни bcrypt, ни scrypt, с хэшем SHA2.
  • Сбросьте все пароли, когда база данных взломана.
  • Реализуйте разумную минимальную длину 8-10 символов, плюс требуйте как минимум 1 заглавную букву, 1 строчную букву, число и символ. Это улучшит энтропию пароля, что, в свою очередь, усложнит его взлом. (См. Раздел «Что делает хороший пароль?» Для некоторых дебатов.)

Зачем хешировать пароли?

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

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

Иеремия Гроссман, технический директор Whitehat Security, заявил в блоге White Hat Security после недавнего восстановления пароля, которое требовало взлома его защиты паролем:

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

(Акцент мой.)

Что делает хороший пароль в любом случае?

Энтропия . (Не то чтобы я полностью разделяю точку зрения Рэндалла.)

Короче говоря, энтропия - это то, насколько сильно варьируется пароль. Когда пароль состоит только из строчных латинских букв, это всего 26 символов. Это не большая вариация. Буквенно-цифровые пароли лучше, с 36 символами. Но допускается верхний и нижний регистр с символами, примерно 96 символов. Это намного лучше, чем просто буквы. Одна проблема состоит в том, чтобы сделать наши пароли запоминающимися, мы вставляем шаблоны, что уменьшает энтропию. К сожалению!

Энтропия пароля легко аппроксимируется . Использование полного диапазона символов ascii (примерно 96 набираемых символов) дает энтропию 6,6 на символ, что при 8 символах для пароля все еще слишком мало (52,679 бит энтропии) для будущей безопасности. Но есть и хорошая новость: более длинные пароли и пароли с символами Юникода действительно увеличивают энтропию пароля и усложняют его взлом.

На сайте Crypto StackExchange обсуждается вопрос об энтропии паролей . Хороший поиск в Google также даст много результатов.

В комментариях я говорил с @popnoodles, который указал, что применение политики паролей длиной X с множеством букв, цифр, символов и т. Д. Может реально уменьшить энтропию, сделав схему паролей более предсказуемой. Я согласен. Randomess, как можно более случайный, всегда является самым безопасным, но наименее запоминающимся решением.

Насколько я могу судить, лучший пароль в мире - это Catch-22. Либо это не запоминающееся, слишком предсказуемое, слишком короткое, слишком много символов Юникода (трудно набрать на устройстве Windows / Mobile), слишком длинный и т. Д. Ни один пароль не достаточно хорош для наших целей, поэтому мы должны защищать их, как если бы они были в форте Нокс.

Лучшие практики

Bcrypt и scrypt являются текущими лучшими практиками. Scrypt будет лучше, чем bcrypt во времени, но он не видел принятия в качестве стандарта Linux / Unix или веб-серверами и еще не опубликовал подробные обзоры своего алгоритма. Но все же будущее алгоритма выглядит многообещающим. Если вы работаете с Ruby , вам поможет Scrypt Gem , и теперь у Node.js есть собственный пакет Scrypt . Вы можете использовать Scrypt в PHP либо через Scrypt расширения или Libsodium расширения (оба доступны в PECL).

Я настоятельно рекомендую прочитать документацию по функции crypt, если вы хотите понять, как использовать bcrypt, или найти себе хорошую обертку, или использовать что-то вроде PHPASS для более унаследованной реализации. Я рекомендую минимум 12 раундов bcrypt, если не 15-18.

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

Средние практики

Я почти не могу представить эту ситуацию больше. PHPASS поддерживает PHP 3.0.18–5.3, поэтому его можно использовать практически во всех возможных установках, и его следует использовать, если вы точно не знаете, что ваша среда поддерживает bcrypt.

Но предположим, что вы не можете использовать bcrypt или PHPASS вообще. Что тогда?

Попробуйте реализовать PDKBF2 с максимальным количеством раундов, которое может выдержать ваша среда / приложение / восприятие пользователя. Наименьшее число, которое я бы порекомендовал - 2500 раундов. Кроме того, обязательно используйте hash_hmac (), если он доступен, чтобы сделать операцию труднее воспроизвести.

Будущие практики

В PHP 5.5 появилась библиотека с полной защитой паролем, которая избавляет от любых трудностей при работе с bcrypt. Хотя большинство из нас придерживаются PHP 5.2 и 5.3 в большинстве распространенных сред, особенно на хостах общего пользования, @ircmaxell создал уровень совместимости для предстоящего API, который обратно совместим с PHP 5.3.7.

Криптография Резюме и отказ от ответственности

Вычислительная мощность, необходимая для взлома хешированного пароля, не существует. Единственный способ «взломать» пароль для компьютеров - это воссоздать его и смоделировать алгоритм хеширования, используемый для его защиты. Скорость хэша линейно связана с его способностью к грубому принуждению. Хуже того, большинство алгоритмов хеширования можно легко распараллелить, чтобы они работали еще быстрее. Вот почему такие дорогостоящие схемы, как bcrypt и scrypt, так важны.

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

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

979
30.11.2019 20:35:26
секрет не помогает, так как ваша база паролей в любом случае должна быть секретной - если они могут завладеть этой базой данных, они также могут найти любой секрет, который вы используете. однако важно, чтобы соль была случайной.
frankodwyer 30.12.2008 23:07:05
обратите внимание, это не совсем так, что «вычислительная мощность для расшифровки» еще не существует. Поскольку большинство паролей являются словарными словами или производными от словаря, атака на основе словаря обычно очень эффективна (следовательно, используется политика паролей и число итераций).
frankodwyer 31.12.2008 00:51:34
@ злая блоха, я не спорю с тобой. Просто указываю, насколько сложна и сложна эта область нашей работы. Я продолжаю надеяться, что меня научит лучшая, самая умная, лучшая практика по настройке системы управления контентом небольшого веб-сайта. Я все еще учусь здесь. ... каждый раз, когда я читаю что-то, что имеет смысл, я скоро замечаю 5 других сообщений, которые противоречат этому. что кругом кругом быстро
m42 26.05.2009 00:16:09
Интересная ревизия. Является ли идентификатор пользователя (скажем, автоинкремент BIGINT) хорошим одноразовым номером? Или, поскольку это не случайно, это не хорошо? Кроме того, мне придется хранить одноразовые номера для каждого пользователя в базе данных ... Обеспечивает ли ключ сайта + nonce + HMAC значительную улучшенную защиту по сравнению с хеш-кодом (с идентификатором пользователя), повторяющимся несколько раз? Точно так же многократно повторяется HMAC для безопасности?
luiscubal 7.07.2010 20:07:35
Отправка временного пароля по электронной почте, который требует, чтобы пользователь изменил его при первом использовании, и отправка «безопасной» ссылки по электронной почте, которая позволяет ему установить свой пароль, в равной степени рискованны. В любом случае любой, кто перехватывает электронную почту, может получить доступ к учетной записи, если он использует ссылку или пароль до того, как это сделает предполагаемый получатель.
Tim Gautier 2.08.2012 21:10:21

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

43
17.01.2013 14:22:05
не для хеширования пароля. злоумышленнику нужно только взломать один хеш, чтобы восстановить пароль. в любом случае это спорный вопрос, поскольку ни MD5, ни SHA1 не имеют практических разрывов в сценарии с паролями.
frankodwyer 30.12.2008 23:05:42
извините, я неверно истолковал ваш ответ как рекомендацию использовать два хэша ... вы на самом деле правы. Использование двух хешей ослабляет систему в случае пароля, поскольку им нужно только сломать более слабый хеш.
frankodwyer 30.12.2008 23:37:40

Я обычно использую SHA1 и соль с идентификатором пользователя (или другой информацией, специфичной для пользователя), а иногда я дополнительно использую постоянную соль (поэтому у меня есть 2 части соли).

SHA1 теперь также считается несколько скомпрометированным, но в гораздо меньшей степени, чем MD5. Используя соль (любую соль), вы предотвращаете использование универсальной радужной таблицы для атаки на ваши хэши (некоторые люди даже добились успеха, используя Google как своего рода радужную таблицу при поиске хеша). Злоумышленник может сгенерировать радужную таблицу, используя вашу соль, поэтому вы должны добавить соль, специфичную для пользователя. Таким образом, им придется генерировать радужную таблицу для каждой записи в вашей системе, а не только для всей вашей системы! При таком типе посола даже MD5 прилично безопасен.

6
30.12.2008 22:18:25
постоянная соль - не лучшая идея ... вероятно, не фатальный недостаток, но это излишне ослабляет схему.
frankodwyer 30.12.2008 23:08:30
MD5 и SHA1 быстрые, так что это плохая смерть.
CodesInChaos 5.03.2014 12:40:55

Google говорит, что SHA256 доступен для PHP.

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

12
30.12.2008 22:20:54
64 бит должно быть достаточно для всех?
Konerak 21.06.2011 12:32:16
@ Konerak, я вернусь к этому через 20 лет. :) Но да, SHA256 действительно доступен. Если вы хотите узнать, насколько безопасен SHA256, вы можете проверить это: security.stackexchange.com/questions/90064/…
Vincent Edward Gedaria Binua 3.12.2015 22:18:44

SHA1 и соли должно хватить (в зависимости, естественно, от того, кодируете ли вы что-нибудь для Fort Knox или систему входа в список покупок) в обозримом будущем. Если SHA1 недостаточно хорош для вас, используйте SHA256 .

Идея соли состоит в том, чтобы вывести из равновесия результаты хеширования. Например, известно, что MD5-хэш пустой строки имеет вид d41d8cd98f00b204e9800998ecf8427e. Итак, если кто-то с достаточно хорошей памятью увидит этот хэш и узнает, что это хэш пустой строки. Но если строка соленая (скажем, со строкой « MY_PERSONAL_SALT»), хеш для «пустой строки» (то есть « MY_PERSONAL_SALT») становится aeac2612626724592271634fb14d3ea6, следовательно, не очевидным для обратной трассировки. Что я пытаюсь сказать, что лучше использовать любую соль, чем не делать этого. Поэтому не так уж важно знать, какую соль использовать.

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

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

4
30.12.2008 22:29:51
Целевой сайт не должен содержать ничего слишком чувствительного (это не банк), но все же я бы предпочел обеспечить его безопасность.
luiscubal 30.12.2008 22:24:36
двойное хеширование не уменьшает пространство результата. итеративное хеширование - это общий контроль над атаками по словарю и методом "грубой силы" (это замедляет их намного больше, чем замедляет проверку пароля).
frankodwyer 30.12.2008 23:10:03
@frankodwyer: да, это плохо. sha1(sha1($foo))эффективно уменьшает выходное пространство, потому что любое столкновение внутренней функции автоматически становится столкновением внешней. Деградация линейная, но это все еще проблема. Методы итеративного хеширования возвращают данные в каждом раунде, например $hash = sha1(sha1($salt . $password) . $salt). Но это все еще не хорошо ... Палка с PBKDF2 или Bcrypt ...
ircmaxell 13.09.2012 14:40:10

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

8
30.12.2008 22:29:28
многократное хеширование также защищает от словарных и грубых атак, т. е. просто увеличивает время вычислений.
frankodwyer 30.12.2008 23:00:55
двойное хеширование не даст вам существенного преимущества, но итерации с многократным хешированием по-прежнему являются реальной защитой от атак по словарю и по методу брюса Промышленные хеши паролей используют более 1000 раундов. PBKDF1 PKCS # 5 предлагает минимум 1000 раундов.
Berk D. Demir 1.01.2009 22:17:14

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

Более подробное объяснение доступно на http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

Недавно я обсуждал вопрос о том, являются ли хеши паролей со случайными битами более безопасными, чем хэши с вероятными или известными солями. Давайте посмотрим: если система хранения пароля скомпрометирована так же, как и система, которая хранит случайную соль, злоумышленник будет иметь доступ к хешу, а также к соли, так что, является ли соль случайной или нет, не имеет значения. Атакующий может генерировать предварительно вычисленные радужные таблицы, чтобы взломать хеш. Здесь возникает интересная часть - это не так тривиально генерировать предварительно вычисленные таблицы. Давайте рассмотрим пример модели безопасности WPA. Ваш пароль WPA фактически никогда не отправляется беспроводной точке доступа. Вместо этого он хэшируется с вашим SSID (сетевое имя, такое как Linksys, Dlink и т. Д.). Очень хорошее объяснение того, как это работает, здесь. Чтобы восстановить пароль из хэша, вам нужно будет знать как пароль, так и соль (имя сети). Church of Wifi уже предварительно вычислил хеш-таблицы, которые имеют 1000 лучших SSID и около 1 миллиона паролей. Размер всех таблиц составляет около 40 ГБ. Как вы можете прочитать на их сайте, кто-то использовал 15 массивов FGPA в течение 3 дней для генерации этих таблиц. Предполагая, что жертва использует SSID в качестве «a387csf3» и пароль в качестве «123456», будут ли они взломаны этими таблицами? Нет! .. оно не может. Даже если пароль слабый, в таблицах нет хэшей для SSID a387csf3. Это красота наличия случайной соли. Это будет сдерживать взломщиков, которые процветают на предварительно вычисленных столах. Может ли это остановить решительного хакера? Возможно нет. Но использование случайных солей обеспечивает дополнительный уровень защиты. Пока мы на эту тему, давайте обсудим дополнительное преимущество хранения случайных солей в отдельной системе. Сценарий # 1: хеши паролей хранятся в системе X, а значения соли, используемые для хеширования, хранятся в системе Y. Эти солт-значения являются предположительными или известными (например, имя пользователя). Сценарий # 2: хеши паролей хранятся в системе X, а значения соли используются для хеширование хранится в системе Y. Эти значения соли являются случайными. Как вы можете догадаться, если система X была скомпрометирована, то использование случайной соли в отдельной системе дает огромное преимущество (сценарий № 2). Атакующий должен будет угадать дополнительные значения, чтобы иметь возможность взломать хэши. Если используется 32-битная соль, для каждого угаданного пароля может потребоваться 2 ^ 32 = 4 294 967 296 (около 4,2 миллиарда) итераций. Хеши паролей хранятся в системе X, а значения солей, используемые для хеширования, хранятся в системе Y. Эти солт-значения являются предположительными или известными (например, имя пользователя) Сценарий # 2: Хеши паролей хранятся в системе X, а значения солей, используемых для хеширования, сохраняются в Система Y. Эти значения соли являются случайными. Как вы можете догадаться, если система X была скомпрометирована, то использование случайной соли в отдельной системе дает огромное преимущество (сценарий № 2). Атакующий должен будет угадать дополнительные значения, чтобы иметь возможность взломать хэши. Если используется 32-битная соль, для каждого угаданного пароля может потребоваться 2 ^ 32 = 4 294 967 296 (около 4,2 миллиарда) итераций. Хеши паролей хранятся в системе X, а значения солей, используемые для хеширования, хранятся в системе Y. Эти солт-значения являются предположительными или известными (например, имя пользователя) Сценарий # 2: Хеши паролей хранятся в системе X, а значения солей, используемых для хеширования, сохраняются в Система Y. Эти значения соли являются случайными. Как вы можете догадаться, если система X была скомпрометирована, то использование случайной соли в отдельной системе дает огромное преимущество (сценарий № 2). Атакующий должен будет угадать дополнительные значения, чтобы иметь возможность взломать хэши. Если используется 32-битная соль, для каждого угаданного пароля может потребоваться 2 ^ 32 = 4 294 967 296 (около 4,2 миллиарда) итераций. Эти значения соли являются случайными. Как вы можете догадаться, если система X была скомпрометирована, то использование случайной соли в отдельной системе дает огромное преимущество (сценарий № 2). Атакующий должен будет угадать дополнительные значения, чтобы иметь возможность взломать хэши. Если используется 32-битная соль, для каждого угаданного пароля может потребоваться 2 ^ 32 = 4 294 967 296 (около 4,2 миллиарда) итераций. Эти значения соли являются случайными. Как вы можете догадаться, если система X была скомпрометирована, то использование случайной соли в отдельной системе дает огромное преимущество (сценарий № 2). Атакующий должен будет угадать дополнительные значения, чтобы иметь возможность взломать хэши. Если используется 32-битная соль, для каждого угаданного пароля может потребоваться 2 ^ 32 = 4 294 967 296 (около 4,2 миллиарда) итераций.

33
27.06.2012 16:10:17
Даже если злоумышленник получит соль, строка "sitesalt: usersalt: password" по-прежнему устойчива к предварительно вычисленным таблицам, поскольку злоумышленнику необходимо генерировать таблицы для каждого пользователя (поэтому атака становится намного медленнее), если, конечно, не конкретный пользователь ставится целью ...
luiscubal 12.02.2010 16:01:24
Что касается «Даже если злоумышленник получит соль, строка« sitesalt: usersalt: password »все еще устойчива к предварительно вычисленным таблицам», я полностью согласен. Моя точка зрения состоит в том, что сайты, если они сделаны случайными и длинными, сделают систему более безопасной, чем она (сайты) будут предсказуемыми. Я видел, как некоторые люди рекомендовали использовать идентификатор электронной почты и т. Д. Как соль, и я не одобряю это.
Gaurav Kumar 13.02.2010 01:20:03
Вы пропустили то, что я изначально написал. Я сказал использовать случайный одноразовый номер, сохраненный вместе с записью, плюс адрес электронной почты. Добавление адреса электронной почты создает дополнительную энтропию для хакера. С тех пор я переписал свой ответ в пользу bcrypt.
Robert K 23.03.2012 01:15:59

Гораздо более короткий и безопасный ответ - не пишите свой собственный механизм паролей вообще , используйте проверенный и проверенный механизм.

  • PHP 5.5 или выше: password_hash () хорошего качества и является частью ядра PHP.
  • Старые версии PHP: библиотека phpass OpenWall намного лучше, чем большинство других пользовательских кодов - используется в WordPress, Drupal и т. Д.

У большинства программистов просто нет опыта безопасного написания крипто-связанного кода без использования уязвимостей.

Быстрая самопроверка: что такое растяжение пароля и сколько итераций следует использовать? Если вы не знаете ответ, вы должны использовать его password_hash(), поскольку расширение пароля теперь является критически важной функцией механизмов паролей из-за гораздо более быстрых процессоров и использования графических процессоров и FPGA для взлома паролей со скоростью миллиардов угаданий в секунду (с графическими процессорами ).

Например, вы можете взломать все 8-символьные пароли Windows за 6 часов, используя 25 графических процессоров, установленных на 5 настольных ПК. Это перебор, то есть перечисление и проверка каждого 8-символьного пароля Windows , включая специальные символы, и это не атака по словарю. Это было в 2012 году, по состоянию на 2018 год вы могли использовать меньше графических процессоров или быстрее взломать 25 графических процессоров.

Существует также множество атак «радужных таблиц» на пароли Windows, которые выполняются на обычных процессорах и очень быстры. Все это потому, что Windows до сих пор не искажает и не растягивает свои пароли, даже в Windows 10 - не делайте ту же ошибку, что и Microsoft!

Смотрите также:

  • отличный ответ с более подробной информацией о том, почему password_hash()или phpassкак лучше.
  • хорошая статья в блоге, содержащая рекомендуемые «рабочие факторы» (количество итераций) для основных алгоритмов, включая bcrypt, scrypt и PBKDF2.
138
20.03.2018 09:48:43
но эти системы более известны и, возможно, уже взломаны. но это лучше, чем создавать свои собственные, когда вы не знаете, что делаете.
JqueryToAddNumbers 11.02.2012 22:53:49
«Эти системы более известны и, возможно, уже скомпрометированы» - нет никаких причин, по которым хорошо спроектированная система аутентификации должна стать «уже скомпрометированной» только потому, что она более известна. Такие библиотеки, как phpass, написаны экспертами и подробно рассмотрены многими людьми - тот факт, что они хорошо известны, сопровождается подробным обзором разных людей и, скорее всего, означает, что они безопасны.
RichVel 16.02.2012 12:24:31
Учитывая недавние пароли из LinkedIn, Last.fm и других, это довольно актуально. Вы в хорошей компании, не зная, как написать собственный механизм паролей!
RichVel 5.07.2012 14:11:09
@PP - на мой взгляд, вероятность того, что алгоритм хэширования паролей, проверенный экспертами, имеет бэкдор АНБ, очень мала. Шансы того, что кто-то не является настоящим крипто-экспертом, пишут новый механизм хеширования паролей без других уязвимостей, намного ниже. А в типичном веб-приложении используется только хеширование MD5 или SHA-1, что ужасно - даже в превосходной книге Криса Шифлетта по Essential PHP Security рекомендуется MD5 ...
RichVel 14.09.2013 10:55:36
@RichVel - функция password_hash (). Как упоминалось ранее, он встроен в ядро ​​PHP (aka / ext / standard).
CubicleSoft 15.03.2015 12:10:19

Я использую Phpass - простой однофайловый PHP-класс, который можно очень легко реализовать практически в каждом PHP-проекте. Смотрите также Н .

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

Возвращенный хеш может быть сохранен в базе данных как есть. Пример использования для генерации хэша:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

Для подтверждения пароля можно использовать:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);
19
26.06.2012 08:05:12

Я просто хочу отметить, что PHP 5.5 включает API хеширования паролей, который обеспечивает обертку вокруг crypt(). Этот API-интерфейс значительно упрощает задачу хеширования, проверки и перефразирования хэшей паролей. Автор также выпустил пакет совместимости (в форме одного файла password.php, который вы просто requireиспользуете) для тех, кто использует PHP 5.3.7 и более поздние версии и хочет использовать его прямо сейчас.

На данный момент он поддерживает только BCRYPT, но его легко расширить, чтобы включить другие методы хэширования паролей, и поскольку техника и стоимость хранятся как часть хэша, изменения в предпочтительной технике / стоимости хэширования не приведут к аннулированию текущих хэшей. будет автоматически, использовать правильную технику / стоимость при проверке. Он также обрабатывает генерацию «безопасной» соли, если вы явно не определяете свою собственную.

API предоставляет четыре функции:

  • password_get_info() - возвращает информацию о данном хеше
  • password_hash() - создает хеш пароля
  • password_needs_rehash()- проверяет, соответствует ли данный хеш заданным параметрам. Полезно, чтобы проверить, соответствует ли хеш вашей текущей схеме техники / стоимости, позволяя вам при необходимости перефразировать
  • password_verify() - проверяет, что пароль соответствует хешу

В настоящее время эти функции принимают константы паролей PASSWORD_BCRYPT и PASSWORD_DEFAULT, которые на данный момент являются синонимами, с той разницей, что PASSWORD_DEFAULT «может измениться в более новых версиях PHP, если поддерживаются более новые, более сильные алгоритмы хеширования». Использование PASSWORD_DEFAULT и password_needs_rehash () при входе в систему (и при необходимости повторной перефразировки) должно гарантировать, что ваши хэши достаточно устойчивы к атакам методом "грубой силы" и практически не работают для вас.

РЕДАКТИРОВАТЬ: Я только что понял, что это кратко упоминается в ответе Роберта К. Я оставлю этот ответ здесь, так как я думаю, что он предоставляет немного больше информации о том, как он работает, и простоту его использования для тех, кто не знает безопасности.

27
6.07.2014 14:08:05

Я нашел идеальную тему по этому вопросу здесь: https://crackstation.net/hashing-security.htm , я хотел, чтобы вы получили от этого выгоду, вот также исходный код, который обеспечил защиту от атак на основе времени.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>
9
19.09.2013 13:26:29
Вы даете нам решение без использования без использования
Michael 5.05.2016 02:55:48

ТО, ЧТО НУЖНО ЗАПОМНИТЬ

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

SERVER

ПОРТЫ

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

USERNAME

Для всего, что хорошо в мире, не используйте имя пользователя admin, root или что-то подобное. Также, если вы работаете в системе на основе Unix, НЕ делайте доступной учетную запись root, это всегда должно быть только sudo.

ПАРОЛЬ

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

БАЗА ДАННЫХ

SERVER

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

USER

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

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

Как всегда, НЕ делайте этот корень или что-то подобное.

ПАРОЛЬ

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

PHP

ПАРОЛЬ

НИКОГДА не храните пароль в вашей БД, вместо этого храните хеш и уникальную соль, я объясню почему позже.

HASHING

ОДИН СПОСОБ ХЕШИНГА !!!!!!!, Никогда не хэшируйте пароль таким образом, чтобы его можно было перевернуть, Хэши должны быть односторонними, то есть вы не должны переворачивать их и сравнивать их с паролем, вместо этого вы хэшируете введенный пароль Точно так же и сравните два хеша. Это означает, что даже если злоумышленник получит доступ к БД, он не знает, что на самом деле представляет собой пароль, а только его результирующий хеш. Что означает больше безопасности для ваших пользователей в худшем из возможных сценариев.

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

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

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

засол

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

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

ПОЛЬЗОВАТЕЛИ, СОЗДАЮЩИЕ ПАРОЛИ

Если пользователь создает пароль через интерфейс, это означает, что он должен быть отправлен на сервер. Это открывает проблему безопасности, потому что это означает, что незашифрованный пароль отправляется на сервер, и если злоумышленник может прослушать и получить доступ, что вся ваша безопасность в PHP бесполезна. ВСЕГДА передайте данные БЕЗОПАСНО, это делается через SSL, но будьте утомлены, даже если SSL не безупречен (например, недостаток OpenSSL Heartbleed).

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

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

Вот класс PHP, который легко создает хеш и соль для пароля

http://git.io/mSJqpw

14
7.07.2014 19:38:53
Вы должны исключить SHA512 из списка достойных алгоритмов хеширования, потому что он слишком быстрый. Используйте его только в сочетании с PBKDF2. В то время как BCrypt основан на blowfish, сам blowfish представляет собой алгоритм шифрования, а не хеширования.
martinstoeckli 9.04.2014 15:24:39
Как вы храните случайную соль в БД? Я думаю, что вы не хешируете его (нельзя использовать для проверки) и не храните в открытом виде (никаких реальных преимуществ, если злоумышленник может прочитать БД). Итак, как ты это делаешь?
Iazel 12.06.2014 23:00:19
wmfrancia писал: «Соление добавляет к паролю случайную строку, чтобы похожие пароли не появлялись в БД». Это не имеет смысла для меня. Хеши в БД уже будут выглядеть непохожими, потому что это свойство хеш-функций.
H2ONaCl 26.02.2015 03:30:38
В отношении постоянной соли wmfancia пишет: «Как только злоумышленник вычислит одну соль пароля, у него будет соль для всех». То же самое можно сказать, что если хакер выяснит, какое поле БД является солью, у него есть соли для всех из них. Поскольку постоянная соль, вероятно, не будет в БД, это хорошая вещь о постоянной соли.
H2ONaCl 26.02.2015 03:39:07
Конечно, эти комментарии не означают, что случайная соль на пользователя не лучше, чем одна соль на приложение. Это лучше.
H2ONaCl 26.02.2015 07:35:25

Начиная с PHP 5.5, PHP имеет простые, безопасные функции для хеширования и проверки паролей, password_hash () и password_verify ()

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false

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

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

Увеличение стоимости (по умолчанию 10) усложняет хэш-обработку хешей, но также означает, что создание хешей и проверка паролей против них будут более трудоемкими для ЦП вашего сервера.

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

39
25.08.2015 19:08:11

Хорошо, в Fitsy нам нужно соль соль должна быть уникальной, так что давайте его генерировать

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

также нам нужен хеш, я использую sha512, он самый лучший и он в php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

так что теперь мы можем использовать эти функции для генерации безопасного пароля

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

теперь нам нужно сохранить в базе данных нашу переменную $ hash_psw и переменную $ salt

и для авторизации мы будем использовать те же шаги ...

это лучший способ защитить пароли наших клиентов ...

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

-6
8.10.2015 04:05:05
Этот вопрос был о хешах для паролей. 1 sha512считается, что выполнение (даже соленое) недостаточно для защиты паролем. (также, что RNG не является криптографически безопасным, поэтому использование его для генерации пароля рискованно).
luiscubal 8.10.2015 13:53:56
Вы понятия не имеете, что делаете. Прочтите ответы в этом посте, и вы поймете, почему ваш код не просто небезопасен, но и не имеет смысла.
cryptic ツ 9.10.2015 18:12:40
Хорошо. мой код не является безопасным. так дайте мне знать, почему вы используете в своих алгоритмах только sha256 ??? Я знаю, что sha512 является лучшим, почему бы не использовать его ???
shalvasoft 10.10.2015 08:59:07
@shalvasoft sha512 довольно хорош для хэширования общего назначения, но для защиты паролем требуются хэши с очень специфическими свойствами (например, «медлительность», как ни странно, хорошая вещь , а sha512 довольно быстрая). Некоторые люди используют sha512 в качестве строительного блока для создания функций хеширования паролей, но в настоящее время рекомендуемый подход - «использовать bcrypt и следить за scrypt».
luiscubal 11.10.2015 18:37:46