У цьому матеріалі мова піде про бібліотеку brcypt та те, як її використовувати на приктиці. Ми поговоримо про її призначення, розберемо функціонал і тд.

Для чого потрібна бібліотека bcrypt?

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

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

Встановлення бібліотеки

Windows:

pip install bcrypt

MacOS:

pip3 install bcrypt

Linux:

pip install bcrypt

Хешування за допомогою bcrypt

Тепер розглянемо як згенерувати хеш за допомогою bcrypt. Ось приклад програми, яка генерує хеш:

import bcrypt

password = "fisherman204512"
password_to_bytes = password.encode(encoding="utf-8")
salt = bcrypt.gensalt()

hash_password = bcrypt.hashpw(password_to_bytes, salt)
print(hash_password)
b'$2b$12$zh5gI.LiCBuMdTPw9LpJzORv.vE976GN4RZrk5mqzchaY9FTEGtry'

Рядки коду

Пояснення

import bcrypt

Імпортуємо бібліотеку bcrypt.

password = "fisherman204512"

Оголошуємо змінну password та записуємо туди рядок з паролем.

password_to_bytes = password.encode(encoding="utf-8")

Перетворюємо наш щойно оголошений пароль у байт рядок.

salt = bcrypt.gensalt()

Генеруємо сіль.

hash_password = bcrypt.hashpw(password_to_bytes, salt)

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

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

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

b'$2b$12$rZjZodP2jg6KQgN/3x8y4e1SdUxXoPVmj/Me47M.E7RaaAYwCO5ma'

Тепер можемо розглянути ще один приклад, де ми не перетворюємо рядок у байт рядок, а просто оголошуємо його одразу:

password = b"qwerty"
salt = bcrypt.gensalt()

hash_password = bcrypt.hashpw(password, salt)
print(hash_password)
b'$2b$12$Oivb5HmRJMIkTrBUhXjjPe0pWOM75QVTfpcHohTpXbZp8M3pG09aa'

Параметри солі та структура хеша

У функції gensalt() є параметри rounds та prefix. Параметр rounds визначає те, скільки разів наш хеш буде проходити через алгоритм bcrypt. Від параметра rounds залежить і надійність хешу, і також це впливає на час його генерації. Тобто чим більше значення приймає rounds, тим довше генерується хеш. Параметр prefix у свою чергу просто вказує на версію алгоритму bcrypt. Ось приклад застосування цих двох параметрів та як це відобразиться на хеші:

password = b"goldenApple"
salt = bcrypt.gensalt(rounds=14, prefix=b"2b")
hash_password = bcrypt.hashpw(password, salt)

print(salt)
print(hash_password)
b'$2b$14$OVVtHVZ3EziSvwpakyk3pulOBHMIQyO4za7JgIxgW3.A3zngmf7Ay'

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

Структура хеша

Частина хеша

Значення частини

Рожевий колір.

Сіль хешу. Тобто це те значення, яке ми генеруємо за допомогою функції gensalt().

Червоний колір.

Це хеш самого паролю.

Зелений колір.

Це версія алгоритму bcrypt, який використовувався при генерації хешу. Це значення ми вказали у параметрі prefix функції gensalt(). Наприклад, є версії 2a та 2b, де перша вказує на оригінальну версію алгоритму, а друга — на виправлену.

Помаренчевий колір.

Це кількість ітерацій, яку проходить наш хеш через алгоритм bcrypt. Це значення ми раніше вказали у параметрі rounds функції gensalt().

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

password = b"super_milk"
salt = bcrypt.gensalt(rounds=18, prefix=b"2a")
hash_password = bcrypt.hashpw(password, salt)

print(hash_password)
b'$2a$18$1TN9pEm4AQktL4/GUX3/jOL.9.QrokmYOJ9pMKbnoylx1RwtN.YTC'

Ось, тепер вже нові значення rounds та prefix, які також можна побачити у новому хеші. За замовчуванням у хешах використовується версія 2b, якщо параметр prefix взагалі не вказаний.

Порівняння хеша та пароля

За допомогою функції checkpw(), яка повертає True, якщо хеш відповідає паролю та False — якщо ні. ми можемо перевірити, чи відповідає хеш паролю. Приклад застосування checkpw() наведений нижче:

password = b"qwerty"
salt = bcrypt.gensalt()

hash_password = bcrypt.hashpw(password, salt)
print(bcrypt.checkpw(password, hash_password))
True

Ми взяли за основу хеш та пароль з попереднього прикладу, тому у даному випадку ми отримали True у результаті. Тепер використаємо інший хеш та передамо його у функцію:

password = b"qwerty"
hash_password = b'$2b$12$rZjZodP2jg6KQgN/3x8y4e1SdUxXoPVmj/Me47M.E7RaaAYwCO5ma'

print(bcrypt.checkpw(password, hash_password))
False

Тепер хеш невідповідає паролю і звісно ми отримали False.

Підсумок

Отже, у підсумку ми розібрали бібліотеку bcrypt, ознайомилися з її функціями та розглянули структуру хеша. Сподіваюся, що дана стаття була цікава та по-справжньому корисна для вас. Дякую за увагу!

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Mystique Lord
Mystique Lord@nocturnal_reader

Нічний читач

55Прочитань
14Автори
3Читачі
На Друкарні з 14 липня

Більше від автора

Вам також сподобається

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Вам також сподобається