Оптимальний коефіцієнт роботи bcrypt


81

Що було б ідеальним фактором роботи bcrypt для хешування паролів.

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

Можливо, було б краще використовувати коефіцієнт роботи 7, зменшивши загальну хеш-роботу пароля приблизно до .01 с для входу в ноутбук?

Як ви вирішуєте компроміс між безпекою грубих сил та експлуатаційними витратами?


7
Вартість перешкоджає офлайн-атакам. У режимі "Інтернет" ви можете використовувати мінімальну затримку між спробами (наприклад, 5 секунд), щоб запобігти атаці відмови в обслуговуванні.
Ian Boyd


1
Для всіх, хто цікавиться, я просто написав невеликий інструмент Java CLI для тестування продуктивності bcrypt на серверах (що, очевидно, важливо для збалансування безпеки, завантаження сервера та часу відповіді): github.com/cdraeger/hash-performance
Blacklight

Відповіді:


103

Пам'ятайте , що значення зберігається в паролі: $2a$(2 chars work)$(22 chars salt)(31 chars hash). Це не фіксоване значення.

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

Фокус полягає в тому, щоб тримати це приблизно стільки ж часу назавжди у майбутньому разом із Законом Мура. Номер log2, тому щоразу, коли комп’ютери подвоюють швидкість, додайте 1 до номера за замовчуванням.

Визначтеся, як довго ви хочете, щоб груба сила користувацького пароля. Наприклад, для деяких загальновживаних словникових слів, створення вашого облікового запису, мабуть, уже попереджало їх про неміцність пароля. Якщо це одне з 1000 загальновживаних слів, скажімо, і зловмисникові потрібно 0,1 с, щоб перевірити кожне, що купує їм 100 с (ну, деякі слова є більш поширеними ...). Якщо користувач вибрав "загальновживане словникове слово" + 2 цифри, це більше двох годин. Якщо ваша база даних паролів порушена, і зловмисник може отримати лише кілька сотень паролів на день, ви придбали більшість своїх користувачів годинами або днями, щоб безпечно змінити їх паролі. Справа в тому, щоб приділити їм час.

http://www.postgresql.org/docs/8.3/static/pgcrypto.html має декілька випадків для збору паролів, які ви повинні розглянути. Звичайно, паролі, які вони там перелічують, є випадковими буквами. Словникові слова ... Практично кажучи, ви не можете врятувати хлопця, чий пароль - 12345.


8
Це справді відмінна відповідь. Я навіть не розглядав ідею повторного склепування для входу. Дуже дякую!
Кріс

1
Як би працювало перешифрування? Вам довелося б десь зберігати стару вартість роботи bcrypt, щоб ви могли використовувати її для входу в систему, а потім після перевірки їх пароля ви оновите хеш і вартість у базі даних?
Джеррі Саравія

6
@JerrySaravia Краса bcrypt полягає в тому, що вартість зберігається в самому хеші - тому вам не потрібно зберігати нічого зайвого. Просто автентифікуйте поточний хеш, а потім негайно повторно генеруйте хеш з іншою вартістю. Просто!
Mark Locker

@MarkLocker, Дякую Марк! Це B [гарний] склеп! Але якщо серйозно, це значно полегшує ситуацію і є прекрасною справою.
Джеррі Саравія

Гаразд, оскільки мені заборонено редагувати його, оскільки це "неправильна спроба відповісти" (ви, хлопці, навіть читаєте мої правки?), Дозвольте мені коментувати інформацію. Приклад значення: $2y$08$fJS4yx0i8kiOzIBIamZ51OWTMrzyE/4je34Oxhw.5xxp3Es7Ke32W. Причина, яку я намагався відредагувати: Мені було незрозуміло, чи "2 символи працюють" - це цифра, шістнадцятковий чи щось інше, потрібно було перевірити. Ось результат тесту для всіх інших, тому вам не доведеться випробувати його самостійно.
Люк

3

Коротка версія

Кількість ітерацій, які дають принаймні 250 мс для обчислення

Довга версія

Коли BCrypt був вперше опублікований, у 1999 році, вони перелічили фактори вартості за замовчуванням для їх реалізації:

  • звичайний користувач: 6
  • суперкористувач: 8

Вартість bcrypt 6 означає 64 раунди (2 6 = 64).

Вони також зазначають:

Звичайно, яку б вартість люди не вибрали, її слід періодично переоцінювати

  • На момент розгортання в 1976 р. Крипта могла гешувати менше 4 паролів на секунду. (250 мс на пароль)
  • У 1977 році на VAX-11/780 крипту (MD5) можна було оцінити приблизно 3,6 рази на секунду. (277 мс на пароль)

Це надає вам смак таких затримок, які враховували оригінальні реалізатори, коли писали:

  • ~ 250 мс для звичайних користувачів
  • ~ 1 секунда для суперкористувачів.

Але, звичайно, чим довше ви зможете стояти, тим краще. Кожна реалізація BCrypt, яку я бачив, використовується 10як вартість за замовчуванням. І моя реалізація використовувала це. Я вважаю, мені пора збільшити вартість за замовчуванням до 12.

Ми вирішили, що хочемо націлити не менше 250 мс на хеш.

Мій настільний ПК - це процесор Intel Core i7-2700K на частоті 3,50 ГГц. Спочатку я провів тестування реалізації BCrypt 23.01.2014:

1/23/2014  Intel Core i7-2700K CPU @ 3.50 GHz

| Cost | Iterations        |    Duration |
|------|-------------------|-------------|
|  8   |    256 iterations |     38.2 ms | <-- minimum allowed by BCrypt
|  9   |    512 iterations |     74.8 ms |
| 10   |  1,024 iterations |    152.4 ms | <-- current default (BCRYPT_COST=10)
| 11   |  2,048 iterations |    296.6 ms |
| 12   |  4,096 iterations |    594.3 ms |
| 13   |  8,192 iterations |  1,169.5 ms |
| 14   | 16,384 iterations |  2,338.8 ms |
| 15   | 32,768 iterations |  4,656.0 ms |
| 16   | 65,536 iterations |  9,302.2 ms |

введіть тут опис зображення

Майбутнє випробування

Замість того, щоб мати фіксовану константу, вона повинна бути фіксованим мінімумом .

Замість того, щоб мати хеш-функцію пароля:

String HashPassword(String password)
{
   return BCrypt.HashPassword(password, BCRYPT_DEFAULT_COST);
}

це має бути приблизно так:

String HashPassword(String password)
{  
   /*
     Rather than using a fixed default cost, run a micro-benchmark
     to figure out how fast the CPU is.
     Use that to make sure that it takes **at least** 250ms to calculate
     the hash
   */
   Int32 costFactor = this.CalculateIdealCost();
   //Never use a cost lower than the default hard-coded cost
   if (costFactor < BCRYPT_DEFAULT_COST) 
      costFactor = BCRYPT_DEFAULT_COST;

   return BCrypt.HashPassword(password, costFactor);
}

Int32 CalculateIdealCost()
{
    //Benchmark using a cost of 5 (the second-lowest allowed)
    Int32 cost = 5;

    var sw = new Stopwatch();
    sw.Start();
    this.HashPassword("microbenchmark", cost);
    sw.Stop();

    Double durationMS = sw.Elapsed.TotalMilliseconds;

    //Increasing cost by 1 would double the run time.
    //Keep increasing cost until the estimated duration is over 250 ms
    while (durationMS < 250)
    {
       cost += 1;
       durationMS *= 2;
    }

    return cost;
}

І в ідеалі це було б частиною бібліотеки BCrypt кожного, тож замість того, щоб покладатися на користувачів бібліотеки, щоб періодично збільшувати вартість, вартість періодично зростає сама.

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