Кращий спосіб зберігання паролів у базі даних


76

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


1
У мене таке відчуття, що це може бути обманом, але те, що я думав, може бути обманом, виявилося, що стосується фактичних входів в БД, а не просто зберігання входів додатків / сайтів.
TheTXI 05.03.09

1
Не могли б ви пояснити своє запитання, щоб пояснити, чи використовуєте ви функції "шифрування" чи "хешування"? Думаю, ви маєте на увазі останнє, але різниця дуже значна.
іне

Відповіді:


82

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

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


@Quinton: Це майже те, що я роблю. За допомогою бібліотек шифрування .net він буде хешувати пароль, а потім я передаю його в БД і зберігаю як двійковий файл. Я можу порівняти паролі лише шляхом хешування введення користувачем та порівняння їх із тим, що зберігається.
TheTXI 05.03.09

1
Я рекомендую jbcrypt, якщо ви працюєте з java. Надзвичайно простий у використанні
Йенс

13
Ми також зберігаємо солоні паролі. У нашому випадку ми перетворюємо 160-розрядний has у base64 і зберігаємо його у varchar - це просто полегшує ситуацію (рядки легше читати / писати / дивитись). На додаток до загальної солі, ми попередньо солимо за допомогою ідентифікатора користувача (sid або guide), так що двоє користувачів з однаковим паролем не дають однаковий хеш. Це ускладнює атаки на словники (більша вартість процесора) і заважає вам знаходити пароль для кількох одночасно, коли всі обирають один і той же пароль.
Ian Boyd

@IanBoyd, якщо ви не змінили метод солі, ви робите це неправильно. Він повинен бути випадковим, з достатньою ентропією та специфічним для користувача, і в цьому випадку ви дотримуєтесь лише останнього.
Francisco Presencia

@FranciscoPresencia З тих пір я перейшов на bcrypt. Канонічна реалізація bcrypt генерує випадкову сіль для кожного хешу. Канонічна реалізація також перетворює 22-байтовий хеш у base64, придатний для зручного зберігання у varcharстовпці бази даних. Останнім кроком хорошого мислення їх частини є визначення формату їхнього хеш-рядка, де сіль входить до рядка.
Ян Бойд

49

Найкращий метод: ніколи не зберігайте паролі у своїй БД. Тільки його хеші. Посоліть за смаком.


6
mod up, довелося це зробити, просто для жартівки;)
Якуб

15

Я роблю те саме, що ви описали, за винятком того, що воно зберігається як рядок. I Base64 кодує зашифроване двійкове значення. Кількість місця для виділення залежить від алгоритму шифрування / сили шифру.

Я думаю, ви робите це правильно (враховуючи, що ви вживаєте сіль ).


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

За допомогою цих заходів паролі вашого користувача будуть досить добре захищені від:

  1. => атаки в автономному словнику
  2. => атаки живого словника
  3. => атаки відмови в обслуговуванні
  4. => всілякі атаки!

Усі ці заходи можна швидко реалізувати, і це достатньо для мінімальних зусиль! +1 =)
Люк Антінс

Чи пов'язані атаки DOS із захистом паролем?
Arj

1
@ a12jun: якщо на вашому веб-сайті є посилання "забув мій пароль" із простим введенням "вхід" та кнопкою "будь-ласка, згенеруйте новий пароль і надішліть мені його електронною поштою", тоді кожен, хто знає ваш логін, може змусити вас змінити пароль. Якщо він автоматизує це запуск кожні 10 секунд, він може заборонити вам доступ до вашого облікового запису. Якщо він запустить це проти тисяч користувачів, він, мабуть, може змусити багатьох з них не сподобатися вашим послугам. Вказівка ​​№3 може захистити вас від цього, ось що я мав на увазі (це не дуже зрозуміло, мушу визнати). Безпека = конфіденційність, цілісність, доступність .
MiniQuark

8

Оскільки результатом хеш-функції є серія байтів в діапазоні від 0 до 255 (або від -128 до 127, залежно від підписаності вашого 8-бітового типу даних), зберігати його як необроблене двійкове поле є найбільш розумним , оскільки це найбільш компактне представлення і не вимагає додаткових кроків кодування та декодування.

Деякі бази даних або драйвери не мають великої підтримки бінарних типів даних, або іноді розробники просто недостатньо знайомі з ними, щоб почувати себе комфортно. У цьому випадку прийнятним є використання кодування бінарного тексту, наприклад Base-64 або Base-85, і зберігання отриманого тексту в полі символу.

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


Щодо "найкращого" способу проведення хешування, я намагався надати багато відповідей на інші запитання щодо цієї теми:


Якщо ви прочитаєте моє запитання трохи уважніше, ви побачите, що я більше зосереджений на фактичному сховищі з точки зору типу даних та місця, виділеного для поля.
TheTXI 05.03.09

Але +1 за надання додаткової інформації іншим, хто може прийти пізніше.
TheTXI 05.03.09

Прямо на. Схоже, цього не вистачає мені не єдиному;)
erickson

4

Я використовую sha-хеш імені користувача, посібник у веб-конфігурації та пароль, що зберігаються як varchar (40). Якщо вони хочуть грубу силу / словник, їм також доведеться зламати веб-сервер для керівництва. Ім’я користувача розбиває створення таблиці веселки у всій базі даних, якщо вони знаходять пароль. Якщо користувач хоче змінити своє ім'я користувача, я просто одночасно скидаю пароль.

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

я використовував ім’я користувача як додану сіль. Але тоді нам не вдалося перейменувати користувача. Ми перейшли на використання солі за допомогою ідентифікатора користувача, керівництва, sid або чогось іншого сурогатного ключа.
Ian Boyd

Тру, хороший дзвінок. таким чином, вам не доведеться скидати пароль, коли ви перейменовуєте користувача
Шон

3

Простий хеш пароля або навіть (сіль + пароль) загалом недостатній.

подивитися:

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


Чудові зв’язки, які виходять за рамки поверхневих проблем безпеки. Для навмисно повільних алгоритмів чи важливо було б обчислювати хеші на стороні клієнта, щоб не перевантажувати (можливо, вже досить зайнятий) сервер?
cheduardo

Не зовсім. Мета просто зробити його "Трохи" повільнішим. Просто щоб дати вам уявлення. Я можу SHA1 хеш близько 200K паролів в секунду на чотирьохядерній системі. Сумніваюся, комусь потрібно обробляти 200K одночасних входів коли-небудь секунди .... Отже, ви використовуєте таку функцію, як PBKDF2 або bcrypt, щоб уповільнити її, щоб сказати лише 100 хешів в секунду (збільшує часову шкалу грубої сили в 200 разів).
Джеральд Девіс,

3

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

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

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

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

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

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


Не існує такого поняття, як швидкий і сильний, коли справа доходить до хешування. Вибачте. Якщо це швидко для вас, це швидко для нападника грубої сили. Використання функції виведення ключів є дійсним методом посилення пароля.
Джеральд Девіс,

2

Якщо ви працюєте з 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


2

Оскільки ваше питання стосується способу та розміру зберігання, я розгляну це.

Тип сховища може бути як двійковим, так і текстовим (найпоширенішим є 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 000 до 50 000 паролів на секунду, тобто до 200 000 паролів на секунду на чотирьохядерній машині. Графічні процесори можуть хешувати від 100 до 1000 разів стільки паролів в секунду. З такою швидкістю, як атака грубої сили стає прийнятним способом вторгнення. RBKDF2 дозволяє вказати кількість ітерацій для точної настройки того, наскільки "повільним" є ваш хеш. Справа не в тому, щоб поставити систему на коліна, а вибрати кілька ітерацій, щоб ви обмежили верхню межу пропускної здатності хешу (скажімо, 500 хешів в секунду). Подальшим методом перевірки буде включення кількості ітерацій у поле пароля (ітерації + сіль + хеш). Це дозволило б збільшувати кількість ітерацій у майбутньому, щоб йти в ногу з потужнішими процесорами. Щоб бути ще більш гнучким, використовуйте varchar, щоб дозволити потенційно більші / альтернативні хеші в майбутньому.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.