【问题标题】:Creating custom Django encrypted field with Fernet使用 Fernet 创建自定义 Django 加密字段
【发布时间】:2021-06-04 13:29:00
【问题描述】:

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

不兼容

this thread我找到了如下代码:

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 是字节

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

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

【问题讨论】:

  • get_prep_value 是否返回 strbytes 对象?你可能需要.encode()
  • 另外,请不要使用大写标题:)
  • 为标题道歉。根据库文档,加密方法已经返回字节,描述为“fernet token”。
  • 您使用的是自定义字段,对吗? SecureString 在您的代码库中吗?只需将.encode() 放在get_prep_value 的返回值的末尾
  • 不起作用,即使我之前将返回的字节对象转换为字符串。

标签: python-3.x django cryptography field fernet


【解决方案1】:

问题似乎与数据库排序规则有关(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')

【讨论】:

    猜你喜欢
    • 2014-04-30
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多