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

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

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

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

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


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

Ответ 5

  • сохранить хэш с соленой паролем, например, bcrypt (nounce + pwd). Вы можете предпочесть bcrypt через SHA1 или MD5, потому что он может быть настроен на интенсивность процессора, поэтому более интенсивный способ атаки грубой силы.
  • добавьте капчет к форме входа после нескольких ошибок входа (чтобы избежать атак с грубой силой)
  • Если ваше приложение имеет ссылку "забыл мой пароль", убедитесь, что он не отправляет новый пароль по электронной почте, но вместо этого он должен отправить ссылку на (защищенную) страницу, чтобы пользователь мог определить новый пароль (возможно, только после подтверждения какой-либо личной информации, например, даты рождения пользователя, например). Кроме того, если ваше приложение позволяет пользователю определить новый пароль, убедитесь, что вы требуете от пользователя подтверждения текущего пароля.
  • и, очевидно, обеспечить регистрационную форму (как правило, с помощью HTTPS) и самих серверов

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

  • = > Атаки в автономном словаре
  • = > активные словарные атаки
  • = > атак на отказ в обслуживании
  • = > всевозможные атаки!

Ответ 6

Простой хэш пароля или даже (соль + пароль) обычно не достаточен.

см

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. Бесплатные версии можно найти в Интернете для большинства популярных языков.

Ответ 7

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

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

Ответ 8

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

{hashId} ${salt} ${hashed password}

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

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

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

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

Ответ 9

Если вы работаете с 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

Ответ 10

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

Тип хранилища может быть как двоичным, так и текстовым (наиболее часто встречающимся является 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 тыс. Паролей в секунду на четырехъядерном процессоре. Графические процессоры могут использовать от 100x до 1000x столько паролей в секунду. С такими скоростями, как атака грубой силы, становится приемлемым методом вторжения. RBKDF2 позволяет указать количество итераций, чтобы точно настроить, как "медленное" ваше хеширование. Суть заключается в том, чтобы поставить систему на колени, но выбрать несколько итераций, чтобы вы ограничили верхнюю границу пропускной способности хеша (скажем, 500 хешей в секунду). Будущим методом доказательства будет включение количества итераций в поле пароля (итерации + соль + хеш). Это позволит увеличить итерации в будущем, чтобы идти в ногу с более мощными процессорами. Чтобы быть еще более гибким, используйте varchar, чтобы в будущем использовать потенциально большие/альтернативные хэши.

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