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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:07:54