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

AES.MODE_EAX加密遇UnicodeDecodeError问题求助

解决AES-EAX加解密时UnicodeDecodeError及密文不一致问题

问题核心原因

  1. Nonce不一致:你的代码中nonce = uuid.uuid4().bytes是全局动态生成的,每次程序重启或重新运行都会生成新的nonce。如果加密后更换了运行环境/重启程序,解密时使用的nonce和加密时完全不同,导致解密出的字节流是乱码,无法通过UTF-8解码。你提到“固定使用nonce”,但当前逻辑并没有真正固定nonce,这是触发错误的核心原因。
  2. 多余的手动填充:AES-EAX属于流加密模式,不需要像CBC/ECB模式那样手动填充数据到块大小。你手动添加空格填充的操作不仅多余,还可能引入不必要的字符处理风险。
  3. 未利用EAX的认证标签:EAX模式自带消息认证功能,你没有存储和验证认证标签,无法确保密文在存储过程中没有被篡改,这也可能加剧解密乱码问题。

修正步骤与代码实现

方案1:固定nonce(适用于需要相同明文生成相同密文的查询场景)

注意:固定nonce会降低加密安全性,仅适用于对安全性要求较低且需支持密文查询的场景。

import binascii
from Crypto.Cipher import AES

# 固定nonce(可自定义为任意16字节值)
FIXED_NONCE = b'\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef'
STR_KEY = "wq5RdHHfzCW1/2eE"  # 16字符对应AES-128密钥长度

def sym_encrypt(data):
    key = STR_KEY.encode("utf-8")
    cipher = AES.new(key, AES.MODE_EAX, nonce=FIXED_NONCE)
    ciphertext, tag = cipher.encrypt_and_digest(data.encode("utf-8"))
    # 密文与认证标签用冒号分隔,一起转十六进制存储
    return f"{ciphertext.hex()}:{tag.hex()}"

def sym_decrypt(data):
    key = STR_KEY.encode("utf-8")
    ciphertext_hex, tag_hex = data.split(":")
    ciphertext = binascii.unhexlify(ciphertext_hex)
    tag = binascii.unhexlify(tag_hex)
    
    cipher = AES.new(key, AES.MODE_EAX, nonce=FIXED_NONCE)
    plaintext = cipher.decrypt_and_verify(ciphertext, tag)
    return plaintext.decode("utf8")

方案2:动态生成nonce并与密文绑定(更安全)

此方案每个密文对应唯一nonce,避免重复使用nonce的安全风险,但相同明文加密结果不同,无法直接基于密文查询。

import binascii
import uuid
from Crypto.Cipher import AES

STR_KEY = "wq5RdHHfzCW1/2eE"  # 16字符对应AES-128密钥长度

def sym_encrypt(data):
    key = STR_KEY.encode("utf-8")
    nonce = uuid.uuid4().bytes
    cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
    ciphertext, tag = cipher.encrypt_and_digest(data.encode("utf-8"))
    # nonce、密文、认证标签用冒号分隔转十六进制存储
    return f"{nonce.hex()}:{ciphertext.hex()}:{tag.hex()}"

def sym_decrypt(data):
    key = STR_KEY.encode("utf-8")
    nonce_hex, ciphertext_hex, tag_hex = data.split(":")
    nonce = binascii.unhexlify(nonce_hex)
    ciphertext = binascii.unhexlify(ciphertext_hex)
    tag = binascii.unhexlify(tag_hex)
    
    cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
    plaintext = cipher.decrypt_and_verify(ciphertext, tag)
    return plaintext.decode("utf8")

验证说明

  • 方案1中,相同明文每次加密生成相同密文,满足查询需求,但需承担固定nonce的安全风险。
  • 方案2遵循加密安全最佳实践,每个密文对应独立nonce,安全性更高,但无法直接通过密文匹配查询相同明文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:27:32