Одне, про що я не бачив згадуваного тут, хоча це продовження відповіді Маркуса Адамса, полягає в тому, що ви не повинні використовувати жодну інформацію для ідентифікації та автентифікації користувача, якщо існує можливість синхронізації атак , що може використовуйте різницю у часі відгуку, щоб здогадатися, наскільки далеко зайшло порівняння рядків.
Якщо ви використовуєте систему, яка використовує "ключ" для пошуку користувача або облікових даних, ця інформація може поступово вгадуватися з часом, надсилаючи тисячі запитів та вивчаючи час, який потрібно вашій базі даних для пошуку (чи ні знайти) запис. Це особливо вірно, якщо "ключ" зберігається у відкритому тексті замість одностороннього хешу ключа. Ви хотіли б зберегти ключі користувачів у відкритому тексті або в симетрично зашифрованому вигляді, якщо вам потрібно мати можливість відображати ключ користувачеві знову.
Отримавши другу інформацію або "секрет", ви можете спочатку шукати користувача або облікові дані за допомогою "ключа", який може бути вразливим до атаки синхронізації, а потім використовувати функцію порівняння, безпечну для синхронізації, щоб перевірити значення секрет".
Ось реалізація цієї функції Python:
https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727
І це виставляється в hmac
lib (і, можливо, інших):
https://docs.python.org/3/library/hmac.html#hmac.compare_digest
Тут слід зауважити одне, що я не думаю, що такий вид атаки буде працювати на значення, які хешуються або шифруються перед пошуком, оскільки значення, які порівнюються, змінюються випадковим чином щоразу, коли змінюється символ у вхідному рядку. Я знайшов гарне пояснення цього тут .
Тоді рішеннями для зберігання ключів API будуть:
- Використовуйте окремий ключ і секрет, використовуйте ключ, щоб шукати запис, і використовуйте безпечне порівняння часу, щоб перевірити секрет. Це дозволяє вам знову показати користувачеві ключ і секрет для користувача.
- Використовуйте окремий ключ і секрет, використовуйте симетричне, детерміноване шифрування секрету та виконуйте звичайне порівняння зашифрованих секретів. Це дозволяє вам знову показати користувачеві ключ і секрет, і це може позбавити вас від необхідності впроваджувати порівняння, безпечне за часом.
- Використовуйте окремий ключ і секрет, відображайте секрет, хеш і зберігайте його, а потім виконайте звичайне порівняння хешованого секрету. Це позбавляє від необхідності використовувати двостороннє шифрування та додає додаткову перевагу збереження вашої таємниці в безпеці, якщо система порушена. Він має мінус у тому, що ви не можете повторно показати секрет користувачеві.
- Використовуйте один ключ , один раз покажіть його користувачеві, хеш, а потім виконайте звичайний пошук хешованого або зашифрованого ключа. Тут використовується один ключ, але він не може бути показаний користувачеві знову. Має перевагу захищати ключі, якщо система порушена.
- Використовуйте один ключ , один раз покажіть його користувачеві, зашифруйте його та виконайте звичайний пошук зашифрованого секрету. Може бути показаний користувачеві ще раз, але ціною того, що ключі є вразливими, якщо їх система порушена.
З них, я вважаю, що 3 - найкращий баланс безпеки та зручності. Я бачив це на багатьох веб-сайтах під час отримання ключів.
Крім того, я запрошую будь-яких фактичних експертів з питань безпеки критикувати цю відповідь. Я просто хотів винести це там як черговий пункт обговорення.