Предпочтительный метод хранения паролей в базе данных

Какой метод / тип данных вы предпочитаете для хранения паролей в базе данных (желательно SQL Server 2005). В некоторых наших приложениях я делал это сначала с использованием библиотек шифрования .NET, а затем сохранял их в базе данных как двоичные (16). Это предпочтительный метод, или мне следует использовать другой тип данных или выделять больше места, чем 16?


person TheTXI    schedule 05.03.2009    source источник
comment
У меня есть ощущение, что это может быть обман, но то, что я подумал, может быть обманом, оказалось касательно фактических входов в БД, а не просто хранения учетных записей приложений / сайтов.   -  person TheTXI    schedule 05.03.2009
comment
Не могли бы вы прояснить свой вопрос, чтобы объяснить, используете ли вы функции шифрования или хеширования? Я думаю, вы имеете в виду последнее, но разница очень существенная.   -  person ine    schedule 05.03.2009


Ответы (10)


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

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

person Quintin Robinson    schedule 05.03.2009
comment
@Quinton: Я в основном этим и занимаюсь. С библиотеками шифрования .net он хеширует пароль, а затем я передаю его в БД и сохраняю как двоичный. Я могу сравнивать пароли только путем хеширования пользовательского ввода и сравнения его с тем, что хранится. - person TheTXI; 05.03.2009
comment
Я рекомендую jbcrypt, если вы работаете с java. Чрезвычайно простой в использовании - person Jens Schauder; 05.03.2009
comment
Мы также храним соленые пароли. В нашем случае мы конвертируем 160-битное значение в base64 и сохраняем его в varchar - это просто упрощает работу (строки легче читать / писать / смотреть). В дополнение к глобальной соли мы предварительно добавляем идентификатор пользователя (sid или guid), чтобы два пользователя с одним и тем же паролем не давали одинаковый хэш. Это усложняет словарные атаки (увеличивает затраты на ЦП) и предотвращает обнаружение пароля для нескольких одновременно, когда все выбирают один и тот же пароль. - person Ian Boyd; 24.02.2010
comment
@IanBoyd, если вы не изменили солевой метод, вы делаете это неправильно. Он должен быть случайным, с достаточной энтропией и индивидуальным для пользователя, и в этом случае вы соблюдаете только последнее. - person Francisco Presencia; 19.11.2013
comment
@FranciscoPresencia С тех пор я перешел на bcrypt. Каноническая реализация bcrypt генерирует случайную соль для каждого хэша. Каноническая реализация также преобразует 22-байтовый хэш в base64, который можно легко сохранить в столбце базы данных varchar. Последний кусок хорошего обдумывания их части - это определение формата их хэш-строки, в которой соль включается в строку. - person Ian Boyd; 19.11.2013

Предпочтительный метод: никогда не храните пароли в своей БД. Только хеши оного. Посолить по вкусу.

person Assaf Lavie    schedule 05.03.2009
comment
мод, пришлось это сделать, просто для соленой шутки;) - person Jakub; 26.08.2009

Я делаю то же самое, что вы описали, за исключением того, что он хранится как строка. I Base64 кодирует зашифрованное двоичное значение. Объем выделяемого пространства зависит от алгоритма шифрования / надежности шифра.

Я думаю, вы делаете это правильно (учитывая, что вы используете Salt).

person Josh Stodola    schedule 05.03.2009

  1. хранить хэш соленого пароля, например bcrypt (nounce + pwd). Вы можете предпочесть bcrypt, а не SHA1 или MD5, потому что он может быть настроен на интенсивную загрузку ЦП, что увеличивает время атаки методом перебора.
  2. добавить капчу в форму входа после нескольких ошибок входа (чтобы избежать атак методом перебора)
  3. если в вашем приложении есть ссылка «забыл свой пароль», убедитесь, что оно не отправляет новый пароль по электронной почте, а вместо этого должно отправлять ссылку на (защищенную) страницу, позволяющую пользователю определить новый пароль (возможно, только после подтверждения некоторой личной информации, такой как, например, дата рождения пользователя). Кроме того, если ваше приложение позволяет пользователю определять новый пароль, убедитесь, что вы требуете от пользователя подтверждения текущего пароля.
  4. и, очевидно, защитите форму входа (обычно с HTTPS) и сами серверы

Благодаря этим мерам пароли ваших пользователей будут достаточно хорошо защищены от:

  1. => офлайн словарные атаки
  2. => атаки по живому словарю
  3. => атаки отказа в обслуживании
  4. => Атаки всякие!
person MiniQuark    schedule 05.03.2009
comment
Все эти меры могут быть реализованы быстро, и при минимальных усилиях они дают неплохой результат! +1 =) - person Luke Antins; 24.08.2009
comment
Связаны ли атаки DOS с безопасностью паролей? - person Arj; 17.01.2012
comment
@ a12jun: если у вас есть ссылка на забытый пароль на вашем веб-сайте с простым вводом логина, и, пожалуйста, сгенерируйте новый пароль и отправьте его мне по электронной почте, тогда любой, кто знает ваш логин, может заставить вас сменить пароль . Если он автоматизирует запуск каждые 10 секунд, то он может отказать вам в доступе к вашей учетной записи. Если он запустит это против тысяч пользователей, он, вероятно, сможет заставить многих из них не любить ваш сервис. Правило №3 может защитить вас от этого, вот что я имел в виду (должен признать, это было не очень понятно). Безопасность = конфиденциальность, целостность, доступность. - person MiniQuark; 19.01.2012

Поскольку результатом хеш-функции является последовательность байтов в диапазоне от 0 до 255 (или от -128 до 127, в зависимости от подписи вашего 8-битного типа данных), сохранение его как необработанного двоичного поля имеет наибольший смысл. , так как это наиболее компактное представление и не требует дополнительных шагов кодирования и декодирования.

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

Размер необходимого поля определяется хэш-функцией, которую вы используете. MD5 всегда выводит 16 байтов, SHA-1 всегда выводит 20 байтов. Выбрав хеш-функцию, вы обычно застреваете на ней, поскольку для ее изменения требуется сброс всех существующих паролей. Итак, использование поля переменного размера ничего вам не даст.


Что касается «наилучшего» способа выполнения хеширования, я попытался дать много ответов на другие вопросы SO по этой теме:

person erickson    schedule 05.03.2009
comment
Если вы прочитаете мой вопрос немного внимательнее, вы увидите, что я больше сосредоточен на фактическом хранилище с точки зрения типа данных и пространства, выделенного для поля. - person TheTXI; 05.03.2009
comment
Но +1 за предоставление дополнительной информации другим, которые могут прийти позже. - person TheTXI; 05.03.2009
comment
Право на. Похоже, этого не хватает не только мне;) - person erickson; 05.03.2009

Я использую sha-хеш имени пользователя, guid в веб-конфигурации и пароль, хранящийся как varchar (40). Если они хотят перебором / словарём, им также нужно будет взломать веб-сервер для поиска гида. Имя пользователя нарушает создание радужной таблицы по всей базе данных, если они действительно находят пароль. Если пользователь хочет изменить свое имя пользователя, я одновременно сбрасываю пароль.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);
person Shawn    schedule 05.03.2009
comment
Я использовал имя пользователя как добавленную соль. Но тогда мы не смогли переименовать пользователя. Мы перешли на использование соли с идентификатором пользователя, guid, sid или другим суррогатным ключом. - person Ian Boyd; 24.02.2010
comment
Тру, хороший звонок. таким образом вам не нужно сбрасывать пароль при переименовании пользователя - person Shawn; 04.03.2010

Простого хеша пароля или даже (соль + пароль), как правило, недостаточно.

видеть:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

и

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

Оба рекомендуют алгоритмы bcrypt. Бесплатные реализации для большинства популярных языков можно найти в Интернете.

person finnw    schedule 05.03.2009
comment
Отличные ссылки, выходящие за рамки поверхностных соображений безопасности. Для заведомо медленных алгоритмов важно, чтобы хэши вычислялись на стороне клиента, чтобы не перегружать (возможно, уже довольно загруженный) сервер? - person cheduardo; 20.06.2009
comment
Не совсем. Цель состоит в том, чтобы сделать это немного медленнее. Просто чтобы дать вам представление. Я могу использовать SHA1-хэш около 200К паролей в секунду на четырехъядерной системе. Я сомневаюсь, что кому-то нужно обрабатывать 200K одновременных входов в систему за секунду .... Итак, вы используете такую ​​функцию, как PBKDF2 или bcrypt, чтобы замедлить ее, чтобы сказать только 100 хэшей в секунду (увеличивает временную шкалу грубой силы в 200 раз). - person Gerald Davis; 17.11.2010

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

{hashId} $ {salt} $ {хешированный пароль}

где «hashId» - это просто некоторое число, которое я использую для внутреннего использования, чтобы распознать, например, что я использую SHA1 с определенным шаблоном хеширования; «соль» представляет собой случайную соль, закодированную в кодировке base64; а «хешированный пароль» - это хеш в кодировке base64. Если вам нужно перенести хэши, вы можете перехватить людей со старым форматом пароля и заставить их изменить свой пароль при следующем входе в систему.

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

Наконец, стоимость использования паролей в кодировке base64 невелика по сравнению с преимуществами возможности использовать различные инструменты, которые ожидают текстовые данные. Да, они должны быть более гибкими, но готовы ли вы сказать своему боссу, что он не может использовать свой любимый сторонний инструмент, потому что вы хотите сэкономить несколько байтов на запись? :-)

Отредактировано, чтобы добавить еще один комментарий: если бы я предложил намеренно использовать алгоритм, который сжигал бы даже 1/10 секунды хеширования каждого пароля, мне бы повезло, если бы меня просто высмеяли из офиса моего босса. (Не так повезло? Он записал бы что-нибудь, чтобы обсудить в моем следующем ежегодном обзоре.) Сжечь это время - не проблема, когда у вас десятки или даже сотни пользователей. Если вы набираете 100 тыс. Пользователей, как правило, в систему одновременно входят несколько человек. Вам нужно что-то быстрое и сильное, а не медленное и сильное. "А как насчет информации о кредитной карте?" в лучшем случае неискренне, поскольку хранимая информация о кредитных картах не должна находиться рядом с вашей обычной базой данных и в любом случае будет зашифрована приложением, а не отдельными пользователями.

person bgiles    schedule 23.03.2009
comment
Когда дело доходит до хеширования, не бывает такого понятия, как быстрое и надежное. Прости. Если это быстро для вас, это быстро для атакующего грубой силы. Использование функции получения ключа - верный метод усиления пароля. - person Gerald Davis; 17.11.2010

Если вы работаете с ASP.Net, вы можете использовать встроенный API членства.

Он поддерживает множество типов хранилищ, в том числе; односторонний хэш, двустороннее шифрование, md5 + соль. http://www.asp.net/learn/security для получения дополнительной информации.

Если вам не нужно ничего особенного, это отлично подходит для веб-сайтов.

Если вы не используете ASP.Net, вот хорошая ссылка на несколько статей от 4guys и codeproject.

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx < / а>

person Sruly    schedule 05.03.2009

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

Тип хранилища может быть двоичным или текстовым (наиболее распространенным является base64). Двоичный формат меньше, но мне легче работать с текстом. Если вы выполняете посол для каждого пользователя (различная соль для каждого пароля), тогда проще сохранить соль + хеш как одну комбинированную строку.

Размер зависит от алгоритма хеширования. Выходные данные MD5 всегда 16 байтов, SHA1 всегда 20 байтов. SHA-256 и SHA-512 составляют 32 и 64 байта соответственно. Если вы используете кодировку текста, вам потребуется немного больше места для хранения в зависимости от метода кодирования. Я предпочитаю использовать Base64, потому что хранение относительно дешево. Base64 потребуется примерно на 33% больше поля.

Если у вас есть посол для каждого пользователя, вам также понадобится место для хеша. Собирая все вместе 64-битная соль + хэш SHA1 (160 бит), кодировка base64 занимает 40 символов, поэтому я сохраняю его как char (40).

Наконец, если вы хотите сделать это правильно, вам следует использовать не один хэш, а функцию получения ключа, такую ​​как RBKDF2. Хеши SHA1 и MD5 безумно быстрые. Даже однопоточное приложение может хэшировать от 30 до 50 тысяч паролей в секунду, что на четырехъядерном компьютере составляет до 200 тысяч паролей в секунду. Графические процессоры могут хэшировать в 100-1000 раз больше паролей в секунду. С такой скоростью атаки методом грубой силы становятся приемлемым методом вторжения. RBKDF2 позволяет вам указать количество итераций для точной настройки того, насколько «медленным» будет ваше хеширование. Дело не в том, чтобы поставить систему на колени, а в том, чтобы выбрать количество итераций, чтобы вы ограничили верхний предел пропускной способности хеширования (скажем, 500 хешей в секунду). В будущем можно будет указать количество итераций в поле пароля (итерации + соль + хеш). Это позволит увеличить количество итераций в будущем, чтобы идти в ногу с более мощными процессорами. Чтобы быть еще более гибким, используйте varchar, чтобы в будущем разрешить потенциально большие / альтернативные хеши.

Реализация .Net - это RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

person Gerald Davis    schedule 16.11.2010