Симметричное шифрование с использованием Fernet в Python — вариант использования главного пароляPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Симметричное шифрование с использованием Fernet в Python — вариант использования главного пароля

Сообщение Anonymous »

Я пытался понять, как работает симметричное шифрование и как я могу интегрировать его в свое приложение CLI, но в какой-то момент застрял, о чем собираюсь рассказать ниже.

Мой вариант использования следующий:
  • У меня есть приложение CLI (

    Код: Выделить всё

    SQLAlchemy
    + щелчок + Python 3.8), который будет очень простым менеджером паролей (для личного использования).
  • При запуске я хочу запросить у пользователя главный пароль, чтобы он мог получить любую информацию из БД. Если у пользователя еще нет мастер-пароля, я попрошу его создать его. Я хочу, чтобы все данные были зашифрованы одним и тем же мастер-ключом.
Чтобы сделать все вышеперечисленное, я подумал симметрично шифрование было бы наиболее подходящим, и на ум пришел Фернет, поэтому я начал писать код:

Код: Выделить всё

import base64

from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

def generate_key_derivation(salt, master_password):
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = base64.urlsafe_b64encode(kdf.derive(master_password.encode()))
return key

def encrypt(key, value_to_encrypt):
f = Fernet(key)
encrypted_key = f.encrypt(value_to_encrypt.encode())
return encrypted_key

def decrypt(key, encrypted_key):
f = Fernet(key)
try:
return f.decrypt(encrypted_key)
except InvalidToken:
return b''
Теперь я попытался понять из документации следующее:


В В этой схеме соль должна храниться в доступном месте, чтобы
получить тот же ключ из пароля в будущем.


Что в моей голове означает: хранить соль в БД и использовать ее каждый раз, когда пользователь пытается использовать приложение. Затем запустите мастер-пароль, введенный пользователем, с помощью функции получения ключа и проверьте, соответствует ли он… ключу? Но исходного ключа у меня нет, так как я не сохранил его в первый раз вместе с солью. И если бы я его сохранил, разве никто не смог бы просто использовать его для шифрования и дешифрования данных?

Какое обычное решение используется предотвратить вышеперечисленное?

Вот небольшой POC с использованием щелчка:

Код: Выделить всё

import os
import click

from models import MasterPasswordModel

@click.group(help="Simple CLI Password Manager for personal use")
@click.pass_context
def main(ctx):
# if the user hasn't stored any master password yet,
# create a new one
if MasterPasswordModel.is_empty():

# ask user for a new master password
master_password = click.prompt(
'Please enter your new master password: ',
hide_input=True
)

# generate the salt
salt = os.urandom(16)

# generate key_derivation
# this isn't stored because if it does anyone would be able
# to access any data
key = generate_key_derivation(salt, master_password)

# store the salt to the DB
MasterPasswordModel.create(salt)

# if the user stored a master password, check if it's valid and
# allow him to do other actions
else:
# ask user for existing master password
master_password = click.prompt(
'Please enter your new master password: ',
hide_input=True
)

# get existing master password salt from DB
salt = MasterPasswordModel.get_salt()

# generate key_derivation
key = generate_key_derivation(salt, master_password)

# At this point I don't know how to check whether the `key` is
# valid or not since I don't have anything to check it against.

# what am I missing?
Надеюсь, все это имеет смысл. Как TL;DR, я думаю, что вопрос будет заключаться в следующем: как я могу безопасно сохранить ключ, чтобы иметь возможность получить его для дальнейших проверок? Или именно так и следует поступать? Что мне не хватает? Я уверен, что что-то недопонимаю :)



ЛЕ: Как указано в одном из комментариев, это Похоже, у меня есть решение, но я все еще застреваю где-то в процессе. В этом ответе указано, что:


Если вы еще этого не делаете, я также настоятельно рекомендую не делать
с использованием предоставленного пользователем ключа напрямую
, но вместо этого сначала передавая его
через намеренно медленную функцию получения ключа, такую ​​как PBKDF2 ,
bcrypt или scrypt. Вам следует сделать это в первую очередь, прежде чем даже пытаться
проверить правильность ключа и немедленно отказаться от
оригинального, предоставленного пользователем ключ и используйте производный ключ для всего
(как для проверки, так и для фактического шифрования/дешифрования).


Итак , давайте для примера все по шагам:

1) У меня первый раз просят мастер-пароль. Его не существует в БД, поэтому, очевидно, мне нужно его создать и сохранить.

2) Наряду с вновь созданной солью мне нужно сохранить хэш предоставленный главный пароль (для примера я буду использовать SHA-256).

3) Теперь у меня есть запись, содержащая соль и хешированный главный пароль, поэтому я можете продолжить использование приложения. Теперь я хочу создать новую запись в БД, которая предположительно будет зашифрована с помощью моего ключа.

Вопрос в том... какой ключ? Если бы я применил то, что написано выше, мне пришлось бы использовать функциюgener_key_derivation(), используя соль и хешированный главный пароль из БД, и использовать его для шифрования/дешифрования. Но если я это сделаю, не сможет ли кто-нибудь просто взять hash_key, хранящийся в БД, и использовать тот же методgenerate_key_derivation, чтобы делать все, что захочет?

Итак, чего мне не хватает?

Подробнее здесь: https://stackoverflow.com/questions/619 ... d-use-case
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»