AES加密解密中温度字段UTF-16解码错误问题咨询
问题分析与解决方案
你的温度字段解密异常(UnicodeDecodeError或乱码),根源在于两个核心代码逻辑错误,而ID解密正常只是巧合:
1. 重复使用同一个CFB模式Cipher对象加密多组数据
CFB属于流加密模式,同一个AES.new()创建的Cipher对象会维护内部的加密状态。你在encrypt函数里用同一个cipher先加密ID,再加密温度,这会导致温度的加密是基于ID加密后的流状态继续的,而非从初始IV重新开始。但解密时,你是单独对温度密文(带IV)重新初始化Cipher,加密与解密的状态完全不匹配,解密出的字节自然错误,解码成UTF-16时就会触发非法代理对错误或乱码。
2. 填充/去填充逻辑完全错误,且CFB模式根本不需要填充
AES的填充仅针对ECB/CBC这类块加密模式(要求明文长度是块大小的倍数),但CFB是流模式,支持任意长度的明文,完全不需要填充操作。
更关键的是你的操作顺序颠倒:先对字符串填充再编码为UTF-16字节,但UTF-16编码后字节长度与原字符串长度并非1:1(比如中文占2字节、emoji占4字节),填充后的字符串编码后字节数未必符合块要求;解密时你先把字节解码成字符串再去填充,若解密字节已损坏,解码阶段直接就会抛出UnicodeDecodeError,或得到乱码字符串后再去填充,结果自然错误。
修正后的代码
我已修复上述问题,你可以直接测试:
from Cryptodome.Cipher import AES from Cryptodome.Random import get_random_bytes import hashlib import base64 def decrypt(enc, key_hash): print("\nIn Decryption method\n") enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(key_hash, AES.MODE_CFB, iv) plain_bytes = cipher.decrypt(enc[AES.block_size:]) # 解密后直接解码UTF-16,无需去填充 plain_text = plain_bytes.decode('utf-16') return plain_text def encrypt(ID, temperature, key_hash): print("\nIn Encryption method\n") # 先将字符串编码为UTF-16字节,CFB模式无需填充 id_bytes = ID.encode('utf-16') temp_bytes = temperature.encode('utf-16') # 每组数据单独创建Cipher对象与随机IV,避免状态干扰 # 加密ID iv_id = get_random_bytes(AES.block_size) cipher_id = AES.new(key=key_hash, mode=AES.MODE_CFB, iv=iv_id) id_cipher = base64.b64encode(iv_id + cipher_id.encrypt(id_bytes)) # 加密温度 iv_temp = get_random_bytes(AES.block_size) cipher_temp = AES.new(key=key_hash, mode=AES.MODE_CFB, iv=iv_temp) temperature_cipher = base64.b64encode(iv_temp + cipher_temp.encrypt(temp_bytes)) print("Id cipher is '{0}'".format(id_cipher)) print("temp cipher is '{0}'".format(temperature_cipher)) return (id_cipher, temperature_cipher) no = int(input("enter no of records")) key_hash = hashlib.sha256(b"charaka").digest() # 创建加密密钥 for i in range(no): ID = input("enter ID\n") temperature = input("enter temperature\n") (ID_cipher, temperature_cipher) = encrypt(ID, temperature, key_hash) print("Decrypted ID is '{0}'".format((decrypt(ID_cipher, key_hash)))) print("Decrypted temp is '{0}'".format((decrypt(temperature_cipher, key_hash))))
关键修正说明
- 独立的Cipher与IV:ID和温度分别使用新的Cipher对象与随机IV,确保加密和解密的状态完全匹配,不会互相干扰。
- 移除冗余填充逻辑:利用CFB流模式的特性,直接对UTF-16编码后的字节加密,解密后直接解码,避免编码解码过程中的错误。
- 正确的字节处理顺序:加密时先编码字符串为字节再加密,解密时先得到明文字节再解码为字符串,符合字节流处理的正确流程。
修改后,温度字段的解密就不会再出现Unicode错误或乱码问题了。
内容的提问来源于stack exchange,提问作者mani varma
相关产品推荐
相关产品推荐

