Как расшифровать значение на другом сервисе, на котором оно было первоначально зашифровано с помощью Fernet?

Я работаю над проектом, который основан на бэкенде на python. У меня будет Django для "основных" вещей и FastAPI для некоторых краулеров. Я зашифровываю некоторые данные в БД с помощью Django, используя модуль Fernet и пользовательский Field.

class EncryptedField(models.CharField):
    description = "Save encrypted data to DB an read as string on application level."

    def __init__(self, *args, **kwargs):
        kwargs["max_length"] = 1000
        super().__init__(*args, **kwargs)

    @cached_property
    def fernet(self) -> Fernet:
        return Fernet(key=settings.FERNET_KEY)

    def get_internal_type(self) -> str:
        return "BinaryField"

    def get_db_prep_save(
        self, value: Any, connection: BaseDatabaseWrapper
    ) -> Union[memoryview, None]:
        value = super().get_db_prep_save(value, connection)
        if value is not None:
            encrypted_value = self.fernet.encrypt(data=force_bytes(s=value))
            return connection.Database.Binary(encrypted_value)

    def from_db_value(self, value: bytes, *args) -> Union[str, None]:
        if value is not None:
            decrypted_value = self.fernet.decrypt(token=force_bytes(s=value))
            return self.to_python(value=force_str(s=decrypted_value))

Все работает как ожидалось, проблема возникает, когда я пытаюсь расшифровать значение на стороне FastAPI:

def decrypt(value: bytes):
    return Fernet(FERNET_KEY).decrypt(token=value)

Некоторая важная информация:

  • Я дважды проверяю и settings.FERNET_KEY == FERNET_KEY, т.е. я использую один и тот же ключ с обеих сторон.
  • Оба сервиса используют одну и ту же БД, а функция получает разные значения при чтении для нее.
    • Django -> from_db_value -> value -> b"gAAAAABhSm94ADjyQES3JL-EiEX4pH2odwJnJe2qsuGk_K685vseoVNN6kuoF9CRdf2GxiIViOgiKVcZMk5olg7FrJL2cmMFvg=="
    • FastAPI -> from_db_value -> value -> b"pbkdf2_sha256$260000$RzIJ5Vg3Yx8JTz4y5ZHttZ$0z9CuQiPCJrBZqc/5DvxiEcbNHZpu8hAZgmibAe7nrQ=". Я действительно вошел в БД и проверил, что это то значение, которое там хранится.

Поэтому я задаюсь вопросом, есть ли что-то перед from_db_value, что как-то преобразует значение?!

Одной из последних альтернатив может быть расшифровка значения на Django и отправка его непосредственно в FastAPI, но я бы предпочел этого не делать.

Как расшифровать значение на FastAPI?

В FastAPI нет принудительной обработки байтов.

def decrypt(value: bytes):
    return Fernet(FERNET_KEY).decrypt(token=value)

#instead do
def decrypt(value: bytes):
    return Fernet(FERNET_KEY).decrypt(token=force_bytes(s=value))

Тогда функция расшифровки на Django и FastAPI будет выглядеть одинаково. Force_bytes может быть местом, где данные изменяются.

Я бы рекомендовал вам проверить функцию force bytes. Если возможно, покажите нам код в функции force bytes.

Достаточно расшифровать значение:

def decrypt(value: bytes):
    return Fernet(FERNET_KEY).decrypt(token=value)

Вы уверены, что пытаетесь расшифровать одни и те же данные? Для меня это выглядит как зашифрованное поле пароля и какое-то другое поле.

mysql> select first_name, password from users_user where login='test'
+------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+
| first_name                                                                                           | password                                                                                 |
| gAAAAABhSm94ADjyQES3JL-EiEX4pH2odwJnJe2qsuGk_K685vseoVNN6kuoF9CRdf2GxiIViOgiKVcZMk5olg7FrJL2cmMFvg== | pbkdf2_sha256$260000$RzIJ5Vg3Yx8JTz4y5ZHttZ$0z9CuQiPCJrBZqc/5DvxiEcbNHZpu8hAZgmibAe7nrQ= |
Вернуться на верх