Python AES加密解密报encoding without a string argument错误解决
AES加密二进制文件读取解密报错排查
我创建了一个无扩展名的二进制文件,用于存储经AES加密的文本内容,在读取文件尝试解密提取文本时,触发如下报错:
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\conitc11\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1884, in __call__ return self.func(*args) File "c:\Users\conitc11\Desktop\PY\REPORTEBIOSTAR.py", line 338, in LecturaBinario encrypted_text = pad(bytes(content, 'utf-8'), 16) TypeError: encoding without a string argument
初始业务代码
最初编写的加解密、文件读写逻辑如下:
def EncrypConfig(message): entryMessage = pad(bytes(message, 'utf-8'), 16) obj = AES.new(secret_key, AES.MODE_CBC, iv) print('Original message is: ', entryMessage) encrypted_text = obj.encrypt(entryMessage) print('The encrypted text', encrypted_text) return encrypted_text def CreacionBinario(): f = open('cfg', 'wb') columnasConfig[0] = cbDepartamento.get() columnasConfig[1] = '2345G564D5645' columnasConfig[2] = lector.get() EncrypConfig(columnasConfig[0]) print('Texto a encryptar: ' + columnasConfig[0]) f.write((bytes(str(EncrypConfig(columnasConfig[0])), 'utf-8'))) print('Texto encryptado: ' + str(EncrypConfig(columnasConfig[0]))) f.close() def LecturaBinario(): with open('cfg', 'rb') as fh: content = fh.read() print('Content:' + str(content)) encrypted_text = pad(bytes(content, 'utf-8'), 16) rev_obj = AES.new(secret_key, AES.MODE_CBC, iv) decrypted_text = rev_obj.decrypt(encrypted_text) print("Print the full content of the binary file:") print(content) print("DecriptedText: ", decrypted_text.decode('utf-8'))
调试过程
我参考标准AES加解密样例做调试,参考代码如下:
from email.message import Message from os import urandom from Crypto.Cipher import AES from Crypto.Util.Padding import pad # 密文生成逻辑 secret_key = urandom(16) iv = urandom(16) obj = AES.new(secret_key, AES.MODE_CBC, iv) message = pad(bytes('All Users', 'utf-8'), 16) print('Original message is: ', message) encrypted_text = obj.encrypt(message) print('The encrypted text', encrypted_text) # 解密逻辑 rev_obj = AES.new(secret_key, AES.MODE_CBC, iv) decrypted_text = rev_obj.decrypt(encrypted_text) print('The decrypted text', decrypted_text.decode('utf-8'))
调试阶段尝试的两种修改方案均失败,对应现象如下:
- 不对读取到的
content做bytes转换,直接传入pad方法,解密后未输出正确明文,仅返回<built-in method decode of bytes object at 0x0000019C7EFDFC00>的方法引用 - 同时移除pad填充处理和bytes转换,触发
ValueError: Data must be padded to 16 byte boundary in CBC mode报错
修复方案
经过逐行调试定位根因后,共做了三点调整:
- 优化加密函数逻辑:将原
entryMessage = pad(bytes(message, 'utf-8'), 16)调整为message = pad(bytes(str(text), 'utf-8'), 16),同时将AES实例初始化语句移到填充逻辑之前,理顺代码执行顺序 - 修正二进制文件写入逻辑:将原错误的
f.write((bytes(str(EncrypConfig(columnasConfig[0])), 'utf-8')))替换为f.write(EncrypConfig(listOfConfig)),直接写入加密方法返回的原始字节对象。这是最核心的修复点:加密方法返回的本身就是符合CBC模式块长度要求的密文字节流,转成字符串再重新编码会彻底破坏密文结构 - 移除读取逻辑中多余的填充和编码转换:删除原
encrypted_text = pad(bytes(content, 'utf-8'), 16)语句,直接将文件读取到的原始字节内容传入解密方法即可。加密阶段已经完成了符合要求的块填充,读取解密阶段不需要二次处理
修复后可运行代码
secret_key = b'somebinarykey12' iv = b'somebinaryvalue1' def EncrypConfig(text): obj = AES.new(secret_key, AES.MODE_CBC, iv) message = pad(bytes(str(text), 'utf-8'), 16) encrypted_text = obj.encrypt(message) return encrypted_text def CreacionBinario(): f = open('cfg', 'wb') columnasConfig[0] = cbDepartamento.get() columnasConfig[1] = txtContraseñaSave.get() columnasConfig[2] = lector.get() columnasConfig[3] = checkedLilWindow2.get() listOfConfig = [columnasConfig[0], columnasConfig[1], columnasConfig[2], columnasConfig[3]] f.write(EncrypConfig(listOfConfig)) print('Texto a encryptar: ', listOfConfig) print('Texto encryptado: ', EncrypConfig(listOfConfig)) f.close() def LecturaBinario(): with open('cfg', 'rb') as fh: content = fh.read() print('Content:', content) rev_obj = AES.new(secret_key, AES.MODE_CBC, iv) decrypted_text = rev_obj.decrypt(content) print("Print the full content of the binary file:") print(content) print('The decrypted text: ', decrypted_text.decode('utf-8')) listFromFile = list[decrypted_text.decode('utf-8')] return listFromFile[1]
内容的提问来源于stack exchange,提问作者José Timaure
相关产品推荐
相关产品推荐

