Безпечне хешування за допомогою Python Hashlib

| | 0 Comments| 4:25 AM
Categories:

Цей підручник навчить вас створювати захищені хеші за допомогою вбудованої функції модуля hashlib Python.

Розуміння важливості хешування та способів програмного обчислення безпечних хешів може бути корисним, навіть якщо ви не працюєте в сфері безпеки програм. Але чому?

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

У цьому посібнику ми розглянемо, що таке хешування та чим воно відрізняється від шифрування. Ми також розглянемо властивості безпечних хеш-функцій. Потім ми використаємо загальні алгоритми хешування, щоб обчислити хеш відкритого тексту в Python. Для цього ми скористаємося вбудованим модулем hashlib.

Для всього цього та іншого давайте почнемо!

Що таке хешування?

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

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

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

На відміну від шифрування, хешування не є оборотним процесом, тобто ми не можемо перейти від хешу до вхідного повідомлення.

Властивості хеш-функцій

Давайте швидко розглянемо деякі властивості, яким мають задовольняти хеш-функції:

  • Детерміновані: хеш-функції є детермінованими. З огляду на повідомлення m, хеш m завжди однаковий.
  • Стійкість до попереднього зображення: ми вже розглянули це, коли сказали, що хешування не є оборотною операцією. Властивість стійкості прообразу стверджує, що неможливо знайти повідомлення m у вихідному хеші.
  • Стійкість до зіткнень: має бути важко (або обчислювально неможливо) знайти два різні рядки повідомлення m1 і m2, щоб хеш m1 дорівнював хешу m2. Ця властивість називається стійкістю до зіткнення.
  • Стійкість до другого прообразу: це означає, що, маючи повідомлення m1 і відповідний хеш m2, неможливо знайти інше повідомлення m2 таке, що hash(m1) = hash(m2).
  Як розширити сховище Xbox Series X|S

Модуль hashlib Python

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

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

import hashlib

Модуль hashlib надає константи algorithms_available і algorithms_guaranteed, які позначають набір алгоритмів, реалізації яких доступні та гарантовані на платформі відповідно.

Таким чином, algorithms_guaranteed є підмножиною algorithms_available.

Запустіть Python REPL, імпортуйте hashlib і отримайте доступ до констант algorithms_available і algorithms_guaranteed:

>>> hashlib.algorithms_available
# Output
{'md5', 'md5-sha1', 'sha3_256', 'shake_128', 'sha384', 'sha512_256', 'sha512', 'md4', 
'shake_256', 'whirlpool', 'sha1', 'sha3_512', 'sha3_384', 'sha256', 'ripemd160', 'mdc2', 
'sha512_224', 'blake2s', 'blake2b', 'sha3_224', 'sm3', 'sha224'}
>>> hashlib.algorithms_guaranteed
# Output
{'md5', 'shake_256', 'sha3_256', 'shake_128', 'blake2b', 'sha3_224', 'sha3_384', 
'sha384', 'sha256', 'sha1', 'sha3_512', 'sha512', 'blake2s', 'sha224'}

Ми бачимо, що algorithms_guaranteed справді є підмножиною algorithms_available

Як створити хеш-об’єкти в Python

Далі навчимося створювати хеш-об’єкти в Python. Ми обчислимо хеш SHA256 рядка повідомлення за допомогою таких методів:

  • Загальний конструктор new().
  • Спеціальні для алгоритму конструктори

Використання конструктора new().

Ініціалізуємо рядок повідомлення:

>>> message = "techukraine.net is awesome!"

Щоб створити екземпляр хеш-об’єкта, ми можемо використати конструктор new() і передати ім’я алгоритму, як показано:

>>> sha256_hash = hashlib.new("SHA256")

Тепер ми можемо викликати метод update() для хеш-об’єкта з рядком повідомлення як аргументом:

>>> sha256_hash.update(message)

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

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Unicode-objects must be encoded before hashing

Щоб отримати закодований рядок, ви можете викликати метод encode() для рядка методу, а потім використати його у виклику методу update(). Після цього ви можете викликати метод hexdigest(), щоб отримати хеш sha256, що відповідає рядку повідомлення.

sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output:'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

Замість того, щоб кодувати рядок повідомлення за допомогою методу encode(), ви також можете визначити його як рядок байтів, додавши до рядка префікс b таким чином:

message = b"techukraine.net is awesome!"
sha256_hash.update(message)
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

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

  5 найкращих інструментів для аналізу моделі трафіку та як це допомагає вашому бізнесу

Крім того, невелика зміна в рядку повідомлення повинна спричинити різку зміну хешу (також відомий як «ефект лавини»).

Щоб перевірити це, давайте змінимо «a» у «awesome» на «A» та обчислимо хеш:

message = "techukraine.net is Awesome!"
h1 = hashlib.new("SHA256")
h1.update(message.encode())
h1.hexdigest()
# Output: '3c67f334cc598912dc66464f77acb71d88cfd6c8cba8e64a7b749d093c1a53ab'

Ми бачимо, що хеш повністю змінюється.

Використання спеціального для алгоритму конструктора

У попередньому прикладі ми використали загальний конструктор new() і передали «SHA256» як назву алгоритму для створення хеш-об’єкта.

Замість цього ми також можемо використати конструктор sha256(), як показано:

sha256_hash = hashlib.sha256()
message= "techukraine.net is awesome!"
sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

Вихідний хеш ідентичний хешу, який ми отримали раніше для рядка повідомлення «techukraine.net чудово!».

Вивчення атрибутів хеш-об’єктів

Хеш-об’єкти мають кілька корисних атрибутів:

  • Атрибут digest_size позначає розмір дайджесту в байтах. Наприклад, алгоритм SHA256 повертає 256-бітний хеш, що еквівалентно 32 байтам.
  • Атрибут block_size вказує на розмір блоку, який використовується в алгоритмі хешування.
  • Атрибут name — це назва алгоритму, який ми можемо використовувати в конструкторі new(). Пошук значення цього атрибута може бути корисним, якщо хеш-об’єкти не мають описових імен.

Ми можемо перевірити ці атрибути для об’єкта sha256_hash, який ми створили раніше:

>>> sha256_hash.digest_size
32
>>> sha256_hash.block_size
64
>>> sha256_hash.name
'sha256'

Далі розглянемо деякі цікаві програми хешування за допомогою модуля hashlib Python.

Практичні приклади хешування

Перевірка цілісності програмного забезпечення та файлів

Як розробники, ми постійно завантажуємо та встановлюємо програмні пакети. Це справедливо незалежно від того, чи працюєте ви в дистрибутиві Linux, на Windows чи Mac.

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

Це також можна застосувати до файлів на вашій машині. Навіть найменша зміна у вмісті файлу суттєво змінить хеш. Ви можете перевірити, чи файл було змінено, перевіривши хеш.

Ось простий приклад. Створіть текстовий файл “my_file.txt” у робочому каталозі та додайте до нього певний вміст.

$ cat my_file.txt
This is a sample text file.
We are  going to compute the SHA256 hash of this text file and also
check if the file has been modified by
recomputing the hash.

Потім ви можете відкрити файл у двійковому режимі читання (‘rb’), прочитати вміст файлу та обчислити хеш SHA256, як показано:

>>> import hashlib
>>> with open("my_file.txt","rb") as file:
...     file_contents = file.read()
...     sha256_hash = hashlib.sha256()
...     sha256_hash.update(file_contents)
...     original_hash = sha256_hash.hexdigest()

Тут змінна original_hash — це хеш ‘my_file.txt’ у його поточному стані.

>>> original_hash
# Output: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'

Тепер змініть файл “my_file.txt”. Ви можете видалити зайві пробіли на початку перед словом «їде». 🙂

  9 варіантів безкоштовного зберігання файлів у хмарі для особистого та бізнес-користування

Обчисліть хеш ще раз і збережіть його в змінній computed_hash.

>>> import hashlib
>>> with open("my_file.txt","rb") as file:
...     file_contents = file.read()
...     sha256_hash = hashlib.sha256()
...     sha256_hash.update(file_contents)
...     computed_hash = sha256_hash.hexdigest()

Потім ви можете додати простий оператор assert, який підтверджує, чи дорівнює computed_hash оригінальному_hash.

>>> assert computed_hash == original_hash

Якщо файл змінено (що в цьому випадку вірно), ви повинні отримати AssertionError:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

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

Висновок

Сподіваюся, цей посібник допоміг вам дізнатися про створення безпечних хешів за допомогою Python. Ось основні висновки:

  • Модуль hashlib Python надає готові до використання реалізації кількох алгоритмів хешування. Ви можете отримати список гарантованих алгоритмів на вашій платформі за допомогою hashlib.algorithms_guaranteed.
  • Щоб створити хеш-об’єкт, ви можете використовувати загальний конструктор new() із синтаксисом: hashlib.new(“algo-name”). Крім того, ви можете використовувати конструктори, що відповідають певним алгоритмам хешування, наприклад hashlib.sha256() для хешу SHA 256.
  • Після ініціалізації рядка повідомлення для хешування та хеш-об’єкта ви можете викликати метод update() для хеш-об’єкта, а потім метод hexdigest(), щоб отримати хеш.
  • Хешування може бути корисним під час перевірки цілісності програмних артефактів і файлів, зберігання конфіденційної інформації в базах даних тощо.

Далі дізнайтеся, як закодувати генератор випадкових паролів у Python.