You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中使用AES-CTR加密文件遇<Object type <class 'tuple'>>错误求助

Django中AES-CTR加密报错问题解决及替代方案

问题概述

加密txt文件时触发错误:

Object type <class 'tuple'> cannot be passed to C code

问题集中在这段代码:

aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

尝试给ctr加encode会报错:'dict' object has no attribute 'encode';去掉key和ctr的encode则报错:Object type <class 'str'> cannot be passed to C code。

当前在Django中使用AES-128的CTR模式加密,完整代码及调用逻辑如下:

现有代码

加密函数

# AES supports multiple key sizes: 16 (AES128), 24 (AES192), or 32 (AES256).
key_bytes = 16
# Takes as input a 32-byte key and an arbitrary-length plaintext and returns a
# pair (iv, ciphtertext). "iv" stands for initialization vector.
def encrypt(key, testpass):
    assert len(key) == key_bytes
    print(testpass)
    print(key)
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    print(ctr)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(testpass)
    print(iv)
    print(ciphertext)
    return (iv, ciphertext)

调用代码

testpass = Audio_store.objects.all().values_list('password').last()
enkripsi = encrypt("testingtesting11", testpass)

关键信息

打印testpass显示为*('testpass_3kEMV2T.txt',)*,调用testpass.encode("utf-8")无输出。

解决方案

核心问题定位

传入加密函数的testpass是元组而非字符串:values_list('password').last()返回单元素元组,必须先提取其中的字符串值。

步骤1:修正输入参数

修改调用代码,提取元组中的字符串:

testpass_tuple = Audio_store.objects.all().values_list('password').last()
if testpass_tuple:
    testpass = testpass_tuple[0]  # 提取元组内的字符串
    enkripsi = encrypt("testingtesting11", testpass)
else:
    # 处理无数据的边界情况
    pass

更简洁的写法:使用flat=True直接返回字符串

testpass = Audio_store.objects.all().values_list('password', flat=True).last()
if testpass:
    enkripsi = encrypt("testingtesting11", testpass)

步骤2:调整加密函数的参数处理

aes.encrypt()要求传入字节类型数据,需将明文字符串编码为字节:

# 替换原加密行
ciphertext = aes.encrypt(testpass.encode('utf-8'))

修正后的完整加密函数

import binascii
from Crypto.Cipher import AES
from Crypto.Random import Random
from Crypto.Util import Counter

key_bytes = 16

def encrypt(key, testpass):
    assert len(key) == key_bytes, "密钥长度必须为16字节(AES-128)"
    
    # 统一转换为字节类型
    key_data = key.encode('utf-8')
    plaintext_data = testpass.encode('utf-8')
    
    # 生成随机IV并初始化计数器
    iv = Random.new().read(AES.block_size)
    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    
    # 创建密码器并加密
    aes = AES.new(key_data, AES.MODE_CTR, counter=ctr)
    ciphertext = aes.encrypt(plaintext_data)
    
    return (iv, ciphertext)

替代方案:简化版AES加密实现

利用PyCryptodome的内置语法简化CTR模式实现,更适合Django项目:

import base64
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

def aes_encrypt(key, plaintext):
    # AES-128要求密钥16字节
    assert len(key) == 16, "密钥长度需为16字节"
    key = key.encode('utf-8')
    
    # 生成随机nonce(CTR模式用nonce+计数器替代传统IV)
    nonce = get_random_bytes(8)
    cipher = AES.new(key, AES.MODE_CTR, nonce=nonce)
    ciphertext = cipher.encrypt(plaintext.encode('utf-8'))
    
    # 返回base64编码的nonce+密文,方便存储和传输
    return base64.b64encode(nonce + ciphertext).decode('utf-8')

def aes_decrypt(key, encrypted_data):
    assert len(key) == 16, "密钥长度需为16字节"
    key = key.encode('utf-8')
    
    # 解码并拆分nonce和密文
    data = base64.b64decode(encrypted_data)
    nonce = data[:8]
    ciphertext = data[8:]
    
    cipher = AES.new(key, AES.MODE_CTR, nonce=nonce)
    plaintext = cipher.decrypt(ciphertext).decode('utf-8')
    
    return plaintext

# Django调用示例
testpass = Audio_store.objects.all().values_list('password', flat=True).last()
if testpass:
    encrypted_str = aes_encrypt("testingtesting11", testpass)
    # 解密示例
    decrypted_str = aes_decrypt("testingtesting11", encrypted_str)

内容的提问来源于stack exchange,提问作者HelpMePlease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:58:57