Гаразд. Бачачи, як мені потрібно писати про це знову і знову , я зроблю одну останню канонічну відповідь лише на перець.
Очевидний перелік перців
Цілком очевидно, що перець повинен зробити хеш-функції більш захищеними. Я маю на увазі, якщо зловмисник отримує лише вашу базу даних, то паролі користувачів повинні бути захищеними, правда? Здається, логічно, правда?
Ось чому так багато людей вважають, що перець - хороша ідея. Це має сенс".
Реальність перців
У сферах безпеки та криптовалюти "сенсу" недостатньо. Щось повинно бути доказовим і має сенс, щоб це можна було вважати безпечним. Крім того, вона має бути реалізованою в ремонтопридатному способі. Найбезпечніша система, яку неможливо підтримувати, вважається незахищеною (адже якщо якась частина цієї безпеки порушиться, вся система розвалиться).
І перець не підходить ні для перевірки, ні для ремонту моделей ...
Теоретичні проблеми з перцем
Тепер, коли ми поставили сцену, давайте подивимося, що не так з перцями.
Подача одного хешу в інший може бути небезпечним.
У вашому прикладі ви робите hash_function($salt . hash_function($pepper . $password))
.
З минулого досвіду ми знаємо, що "просто подача" одного хеш-результату в іншу хеш-функцію може зменшити загальну безпеку. Причина в тому, що обидві хеш-функції можуть стати об'єктом атаки.
Ось чому такі алгоритми, як PBKDF2, використовують для комбінування спеціальних операцій (hmac у такому випадку).
Справа в тому, що, хоча це не є великою справою, це теж не тривіальна річ, щоб просто кинутись навколо. Криптосистеми розроблені так, щоб уникнути випадків "слід працювати", а замість цього зосереджуватися на "призначених для роботи" випадках.
Хоча це може здатися чисто теоретичним, насправді це не так. Наприклад, Bcrypt не може приймати довільні паролі . Тому передача bcrypt(hash(pw), salt)
дійсно може призвести до набагато слабшого хешу, ніж bcrypt(pw, salt)
якщо hash()
повертає двійковий рядок.
Працюючи проти дизайну
Спосіб розробки bcrypt (та інших алгоритмів хешування паролів) - це робота з сіллю. Поняття перцю так і не було введено. Це може здатися дрібницею, але це не так. Причина в тому, що сіль не є секретом. Це лише значення, яке може бути відоме зловмиснику. З іншого боку, перець, за власним визначенням, є криптографічним секретом.
Поточні алгоритми хешування паролів (bcrypt, pbkdf2 тощо) призначені для отримання лише одного секретного значення (пароля). Додавання ще одного секрету в алгоритм взагалі не вивчалося.
Це не означає, що це не безпечно. Це означає, що ми не знаємо, чи безпечно це. І загальна рекомендація щодо безпеки та криптографії полягає в тому, що якщо ми не знаємо, це не так.
Тому, поки алгоритми не будуть розроблені та перевірені криптографами для використання з таємними значеннями (перцем), поточні алгоритми не повинні використовуватися з ними.
Складність - це ворога безпеки
Вірите чи ні, складність - це ворог безпеки . Створення алгоритму, який виглядає складним, може бути безпечним, а може і не бути. Але шанси досить великі, що це не безпечно.
Значні проблеми з перцем
Це неможливо
Ваша реалізація перців виключає можливість повороту перцевого ключа. Оскільки перець використовується на вході до функції в одну сторону, ви ніколи не можете змінювати перець протягом життя значення. Це означає, що вам потрібно буде придумати кілька непростих хаків, щоб підтримати обертання клавіш.
Це надзвичайно важливо, оскільки це потрібно, коли ви зберігаєте криптографічні таємниці. Немає механізму повороту клавіш (періодично і після порушення) - це величезна вразливість безпеки.
І ваш поточний підхід до перцю вимагає від кожного користувача або мати повний недійсний пароль при обертанні, або чекати, поки наступний логін обернеться (що може бути ніколи) ...
Це, в основному, робить ваш підхід негайним відмовою.
Це вимагає, щоб ви прокатали власну криптовалюту
Оскільки жоден поточний алгоритм не підтримує концепцію перцю, він вимагає або скласти алгоритми, або винайти нові для підтримки перцю. І якщо ви не можете відразу зрозуміти, чому це справді погано:
Будь-який, від найрозумнішого аматора до найкращого криптографа, може створити алгоритм, який він сам не може зламати.
НІКОЛИ не прокатуйте власну криптовалюту ...
Кращий шлях
Отже, з усіх вищеописаних проблем є два способи вирішення ситуації.
Просто використовуйте алгоритми у міру їх існування
Якщо ви правильно використовуєте bcrypt або scrypt (з високою вартістю), всі паролі, крім самих слабких словників, повинні бути статистично безпечними. Поточний рекорд для шифрування bcrypt вартістю 5 становить 71 кш хеш за секунду. З такою швидкістю навіть шість випадкових паролів знадобиться років, щоб зламати. І якщо врахувати, що моя мінімальна рекомендована вартість - 10, це зменшує хеші в секунду в 32 рази. Тому ми говоримо лише про 2200 хешей за секунду. З такою швидкістю навіть деякі словникові фрази або модифікатори можуть бути безпечними.
Крім того, ми повинні перевіряти наявність слабких класів паролів у дверях та не допускати їх. Коли злом паролів стає більш вдосконаленим, так само повинні бути і вимоги до якості пароля. Це все-таки статистична гра, але з належною технікою зберігання та надійними паролями кожен повинен бути практично дуже безпечним ...
Зашифруйте хеш-вихід до зберігання
У царині безпеки існує алгоритм, призначений для обробки всього, про що ми говорили вище. Це блок-шифр. Це добре, тому що він оборотний, тому ми можемо обертати клавіші (так! Ремонтопридатність!). Це добре, тому що використовується як задумано. Це добре, оскільки не дає користувачеві ніякої інформації.
Давайте ще раз подивимось на цей рядок. Скажімо, що зловмисник знає ваш алгоритм (який необхідний для безпеки, інакше це безпека через неясність). При традиційному підході до перцю зловмисник може створити дозорний пароль, і оскільки він знає сіль і вихід, він може жорстоко примусити перець. Гаразд, це дальний постріл, але це можливо. З шифром нападник нічого не отримує. А оскільки сіль є рандомізованим, дозорний пароль навіть не допоможе йому / їй. Тож найкраще, що їм залишається, - це атакувати зашифровану форму. Це означає, що спочатку вони повинні атакувати ваш зашифрований хеш, щоб відновити ключ шифрування, а потім атакувати хеші. Але існує багато досліджень атаки шифрів, тому ми хочемо на це покластися.
TL / DR
Не використовуйте перець. З ними виникає безліч проблем, і є два кращих способи: не використовувати жодних секретів на стороні сервера (так, це нормально) та шифрувати хеш-код виводу за допомогою шифру блоку до зберігання.