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


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

10 76

10 ответов:

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

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

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

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

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

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

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


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

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

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

  1. = > offline словарь атак
  2. = > live dictionary attacks
  3. => отказ в обслуживании
  4. => все виды атак!

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

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

простой хэш пароля, или даже (соль + пароль), как правило, не адекватны.

посмотреть:

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

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

{hashId}${salt}${Hashed password}

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

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

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

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

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

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

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

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

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

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

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