Предпочтительный способ хранения паролей в базе данных - PullRequest
76 голосов
/ 05 марта 2009

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

Ответы [ 10 ]

81 голосов
/ 05 марта 2009

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

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

48 голосов
/ 05 марта 2009

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

15 голосов
/ 05 марта 2009

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

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

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

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

  1. => автономные атаки по словарю
  2. => живые атаки по словарю
  3. => Атаки отказа в обслуживании
  4. => всевозможные атаки!
8 голосов
/ 05 марта 2009

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

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

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


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

4 голосов
/ 06 марта 2009

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

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);
3 голосов
/ 23 марта 2009

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

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

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

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

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

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

3 голосов
/ 05 марта 2009

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

см

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

и

http://gom -jabbar.org / статьи / 2008/12 / 03 / почему вы-должны потребительной Bcrypt-к-магазин-ваши-пароли

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

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

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

Тип хранения может быть двоичным или текстовым представлением (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

2 голосов
/ 05 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...