Безпечне гешування паролів

Цей розділ пояснює причини використання геш-функцій для убезпечення паролів, а також, як це зробити ефективно.

Навіщо мені гешувати користувацькі паролі моєї програми?

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

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

Важливо підкреслити, що гешування паролів лише захищає їх від того, щоб бути скомпрометованими у вашому сховищі даних, але аж ніяк не захищає їх від перехоплення зловмисним кодом, впровадженим у вашу програму.

Чому такі поширені геш-функції як md5() і sha1() не придатні для паролів?

Алгоритми гешування MD5, SHA1 та SHA256 розроблені бути дуже швидкими та ефективними. З сучасною технікою та комп'ютерним обладнанням стало легко зламати результат цих алгоритмів, щоб визначити початковий текст.

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

Як мені гешувати паролі, якщо поширені геш-функції не придатні.

Під час гешування паролів двома найважливішими факторами є витрати на обчислення та т. зв. "сіль". Чим більше обчислень має виконати алгоритм, тим довше триватиме злам результату його обчислень.

PHP має вбудований API гешування паролів, який надає засоби як гешування, так і перевірки паролів безпечним способом.

Інший спосіб — це функція crypt(), яка підтримує декілька алгоритмів гешування. Використовуючи цю функцію, ви гарантовано оберете доступний алгоритм, адже PHP має власну реалізацію кожного підтримуваного алгоритму, навіть якщо один або декілька не підтримуються вашою системою.

Для гешування паролів рекомендується алгоритм Blowfish, який стандартно використовується API гешування паролів, оскільки він є набагато дорожчим в обчисленні, аніж MD5 або SHA1, залишаючись масштабованим.

Зауважте, якщо ви використовуєте crypt() для перевірки пароля, вам необхідно подбати про запобігання часових атак, використовуючи однаковий час для порівняння рядків. Ані оператори == і ===, ані strcmp() не виконують порівняння за однаковий проміжок часу. Тільки password_verify() зробить це для вас, тож дуже просимо використовувати вбудований API гешування паролів за будь-якої можливості.

Що таке "сіль"?

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

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

password_hash() створить випадкову сіль, коли та не вказана, і це, як правило, найпростіший і найбезпечніший підхід.

Як мені зберігати цю сіль?

У password_hash() або crypt() значення, що повертається, містить сіль як частину утвореного гешу. Це значення має бути точно збережене у вашій базі даних, оскільки воно містить інформацію про геш-функцію, яка використовувалася, і потім може бути надано безпосередньо до password_verify() або crypt() під час перевірки паролів.

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


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