DevGang
Авторизоваться

Безопасное управление паролями Python: хеширование и шифрование

При создании приложения, которое проверяет пароли пользователей или требует хранения токенов для будущего использования, крайне важно не хранить эти значения где-либо в виде открытого текста. Если есть нарушение безопасности, вы хотите быть уверены, что данные вашего пользователя защищены. Хеширование и шифрование — это несколько методов, которые можно использовать для достижения этой цели, и мы рассмотрим, как реализовать их с помощью Python.

Хеширование

Если вашему приложению необходимо разрешить пользователям регистрировать учетную запись и создавать пароль, вам необходимо сохранить значения, с которыми они подписались, чтобы позже аутентифицировать их. Вместо хранения паролей в открытом виде следует использовать алгоритм хеширования. Алгоритмы хеширования представляют собой односторонние функции, которые дают один и тот же результат для входных данных, но, учитывая, что выходные данные практически невозможно обратить вспять. Существует много типов хеш-алгоритмов, но SHA-256 — это надежный современный алгоритм, одобренный NIST, который соответствует потребностям большинства приложений с точки зрения надежности и производительности.

Создайте простой файл сценария Python, который будет принимать входные данные и генерировать хэш SHA-256 с помощью стандартной библиотеки hashlib.

hash.py
import hashlib

password = input("Password: ")
password_hash = hashlib.sha256(password.encode("utf-8")).hexdigest()
print(f"Password Hash: {password_hash}")

Запустите скрипт и введите несколько паролей.

$ python3 hash.py
Password: test123
Password Hash: ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae

$ python3 hash.py
Password: test123
Password Hash: ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae

$ python3 hash.py
Password: test1234
Password Hash: 937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244

Мы видим, что одни и те же входные данные дают один и тот же результат хеширования, но любое изменение, например добавление дополнительного символа, полностью меняет его. Полученное хэш-значение — это то, что вы должны сохранить в своей базе данных, чтобы позже проверить пароль пользователя.

Шифрование

Хеширование — отличный вариант, когда вам не нужно использовать значение пароля. В случаях, когда вам необходимо использовать фактическое значение пароля, например, для хранения токена долгосрочного доступа для аутентификации от имени пользователя во внешнем приложении, лучшим вариантом является шифрование. Шифрование позволяет безопасно хранить значения и расшифровывать их в памяти, когда вам нужно их использовать. Для этого в Python есть библиотека криптографии, которая включает в себя симметричное шифрование Fernet. Симметричное шифрование означает, что у нас будет секретный ключ, который мы сможем хранить в переменных среды и использовать для расшифровки сохраненных значений.

Установите библиотеку cryptography и dotenv.

$ poetry add cryptography python-dotenv
Using version ^41.0.5 for cryptography
Using version ^1.0.0 for python-dotenv

Updating dependencies
Resolving dependencies... (0.1s)

Package operations: 4 installs, 0 updates, 0 removals

  • Installing pycparser (2.21)
  • Installing cffi (1.16.0)
  • Installing cryptography (41.0.5)
  • Installing python-dotenv (1.0.0)

Запустите встроенную команду Python, чтобы сгенерировать секретный ключ Fernet.

$ python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key())"
b'XvYvP_c4gBDLCLbjgz6Hc47ND_BcoMYt3Cz5pAKx1qQ='

Добавьте это значение в .env файл.  

.env
SECRET_KEY=XvYvP_c4gBDLCLbjgz6Hc47ND_BcoMYt3Cz5pAKx1qQ=

Создайте новый скрипт Python, который загрузит наш секретный ключ из переменных среды, создаст экземпляр клиента Fernet с этим ключом и позволит зашифровать и сохранить новый пароль в простом текстовом файле или распечатать расшифрованное значение существующего сохраненного пароля.

encrypt.py
import os
import sys

from cryptography.fernet import Fernet
from dotenv import load_dotenv

load_dotenv()

SECRET_KEY = os.getenv("SECRET_KEY")
assert SECRET_KEY
FERNET = Fernet(SECRET_KEY)

if len(sys.argv) > 1 and sys.argv[1] == "decrypt":
    with open("pw.txt") as f:
        stored_password = f.read()

    stored_dec_password = FERNET.decrypt(stored_password).decode()
    print(f"Decrypted Password: {stored_dec_password}")
else:
    new_password = input("New Password: ")
    new_enc_password = FERNET.encrypt(new_password.encode()).decode()

    with open("pw.txt", "w") as f:
        f.write(new_enc_password)

    print(f"Encrypted Password Stored: {new_enc_password}")

Проверьте его, чтобы убедиться, что он работает должным образом.

$ python3 encrypt.py
New Password: Test123!!
Encrypted Password Stored: gAAAAABlR7V0TLTZMT_ZHEoPtqbW3B9LYgohYdUNG6Lukx9M2NSLgrFN6MUZKCNPP3Hq_KuuEPpJPPqqIktUkZTBh3qenKnQAA==

$ python3 encrypt.py decrypt
Decrypted Password: Test123!!

Здесь показаны основные концепции шифрования/дешифрования значений в производственной среде: вместо хранения их в простом текстовом файле вы просто сохраняете и извлекаете значения из базы данных.

Источник:

#Python
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу