如何解密最初使用 Fernet 加密的不同服务上的值?

Mur*_*nio 5 python encryption django fastapi fernet

我正在研究一个基于 python 后端的项目。我将使用 Django 来处理“核心”内容,使用 FastAPI 来处理一些爬虫。Fernet我正在使用模块和自定义Django 将一些数据加密到数据库中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))
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作,问题是当我尝试解密 FastAPI 端的值时:

def decrypt(value: bytes):
    return Fernet(FERNET_KEY).decrypt(token=value)
Run Code Online (Sandbox Code Playgroud)

一些重要信息:

  • 我仔细检查了一下settings.FERNET_KEY == FERNET_KEY,即我两侧都使用相同的密钥。
  • 两个服务共享相同的数据库,并且该函数在读取时接收到不同的值。
    • 姜戈 -> from_db_value-> value->b"gAAAAABhSm94ADjyQES3JL-EiEX4pH2odwJnJe2qsuGk_K685vseoVNN6kuoF9CRdf2GxiIViOgiKVcZMk5olg7FrJL2cmMFvg=="
    • FastAPI -> user.encrypted_field-> value-> b"pbkdf2_sha256$260000$RzIJ5Vg3Yx8JTz4y5ZHttZ$0z9CuQiPCJrBZqc/5DvxiEcbNHZpu8hAZgmibAe7nrQ=". 我实际上进入数据库并检查这是否是存储在那里的值。user来自这里:
      • from sqlmodel import Session, select
        
        from .models import User
        
        
        async def get_user(db: Session, username: str) -> str:
           statement = select(User).where(User.username == username)
           return db.exec(statement).first()
        
        Run Code Online (Sandbox Code Playgroud)

所以我想知道之前有什么东西from_db_value以某种方式转换值?!

最后一种选择是在 Django 上解密该值并将其直接发送到 FastAPI,但我不想这样做。

如何解密 FastAPI 上的值?

cod*_*ire 0

在 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))

Run Code Online (Sandbox Code Playgroud)

那么 Django 和 FastAPI 上的解密函数看起来是一样的。force_bytes 可能是数据发生更改的地方。

我建议您检查强制字节函数。如果可能的话,请向我们展示强制字节函数的代码。