1

我正在尝试使用 Fernet 创建一个 django 自定义加密字段。我发现自动执行此操作的库似乎已过时/与 Django>3.0 不兼容

这个线程中,我发现了以下代码:

import base64

from django.db.models import CharField
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from core import settings


    class SecureString(CharField):
       
    
        salt = bytes(settings.SECURE_STRING_SALT, encoding="raw_unicode_escape")
        kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), 
                         length=32, 
                         salt=salt, 
                         iterations=100000, 
                         backend=default_backend())
    
        key = base64.urlsafe_b64encode(kdf.derive(settings.SECRET_KEY.encode('utf-8')))
        f = Fernet(key)
    
        def from_db_value(self, value, expression, connection):
            return str(self.f.decrypt(value), encoding="raw_unicode_escape")
    
        def get_prep_value(self, value):
            return self.f.encrypt(bytes(value, encoding="raw_unicode_escape"))

它似乎适用于编码部分(如果我使用管理器程序检查数据库字段,内容显示为一种汉字),但不适用于解码。

每次我在 Admin 中保存记录时,都会触发此错误(尽管保存在数据库中):

raise TypeError("{} must be bytes".format(name)) TypeError: token must be bytes

由于get_prep_value代码,不应该已经是数据库记录中的字节吗?尝试在管理员中列出记录(访问读取功能)时会发生相同的错误。

我该如何解决这个问题?我使用 SQL Server 作为数据库(以防它可能相关)。

4

1 回答 1

0

似乎问题与数据库排序规则(Modern_Spanish_CI_AI,cp1252)有关。我必须将字符串从该排序规则转换为该排序规则才能工作。由于数据库是 SQL Server 而不是本机支持的数据库之一,因此不确定这是否有必要。

这行得通。数据在 db 中加密,但作为标准字符而不是中文字符。我想这对我来说应该是一个线索,以便看到排序规则可能是问题所在。

from django.db import models
import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from pymega import settings

class SecureString(models.CharField):    
    salt = bytes(settings.SECURE_STRING_SALT, 'utf-8')
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), 
                     length=32, 
                     salt=salt, 
                     iterations=100000,
                     )
    key = base64.urlsafe_b64encode(kdf.derive(bytes(settings.SECRET_KEY,'utf-8')))    
    f = Fernet(key)
    
    def from_db_value(self, value, expression, connection):
        return str(self.f.decrypt(bytes(value, 'cp1252')), encoding='utf-8')

    def get_prep_value(self, value):       
        return str(self.f.encrypt(bytes(value, 'utf-8')), 'cp1252')
于 2021-06-04T15:44:39.963 回答