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

使用PyCryptodome进行AES-128 CBC加解密时解密结果异常,出现UnicodeDecodeError求助

使用PyCryptodome进行AES-128 CBC加解密时解密结果异常,出现UnicodeDecodeError求助

看起来你的代码里有几个关键问题导致了解密失败,出现UnicodeDecodeError,我来帮你一步步梳理清楚:

问题1:CBC模式缺少初始化向量(IV)的一致性处理

你在加密时用AES.new(akey, AES.MODE_CBC)会自动生成一个随机的IV,但你完全没把这个IV和加密数据一起保存下来。等到解密时,你又新建了一个cipher2 = AES.new(akey, AES.MODE_CBC),这会生成一个全新的随机IV——用不同的IV去解密,得到的必然是乱码,自然在尝试用UTF-8解码时就会抛出UnicodeDecodeError。

问题2:密钥的处理方式不安全且不合理

AES-128要求密钥必须是16字节,你直接用pad(key.encode(), block_size)把短密钥补到16字节,这种做法不仅不安全,还可能因为补位规则的问题引发潜在风险。正确的做法是用哈希函数把任意长度的密钥字符串转换成固定长度的字节串,再截取符合要求的长度作为AES密钥。

修正后的完整代码

加密部分

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Hash import SHA256 as sha256

def derive_key(key_str):
    # 通过SHA256哈希派生符合AES-128要求的16字节密钥
    hash_result = sha256.new(key_str.encode())
    return hash_result.digest()[:16]

key = '1234'
block_size = 16
plain_text = "The quick brown fox jumped over the lazy dog"

# 生成标准的AES-128密钥
akey = derive_key(key)
print('Key length:', len(akey))  # 输出应为16

pt_encoded = plain_text.encode()
# 创建CBC加密器,同时获取自动生成的IV
cipher = AES.new(akey, AES.MODE_CBC)
payload = pad(pt_encoded, block_size)
encrypted = cipher.encrypt(payload)

# 把IV和加密数据一起写入文件(IV在前,加密内容在后)
with open('data.bin', 'wb') as f:
    f.write(cipher.iv)
    f.write(encrypted)

print('Encrypted sha:', sha256.new(encrypted).hexdigest())

解密部分

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Hash import SHA256 as sha256

def derive_key(key_str):
    hash_result = sha256.new(key_str.encode())
    return hash_result.digest()[:16]

key = '1234'
block_size = 16

# 读取文件中的IV和加密数据
with open('data.bin', 'rb') as f:
    iv = f.read(16)  # 先读取前16字节的IV
    encrypted_data = f.read()  # 读取剩余的加密内容

akey = derive_key(key)
# 使用保存的IV创建解密器
cipher2 = AES.new(akey, AES.MODE_CBC, iv=iv)
decrypted = cipher2.decrypt(encrypted_data)

try:
    plain = unpad(decrypted, block_size)
    print('Plain text:', plain.decode())
except ValueError as e:
    print("解密失败,可能是密钥错误或数据被篡改:", e)

额外说明

  • IV不需要保密,但必须和加密时的完全一致才能正确解密,所以一定要和加密数据一起存储。
  • 用哈希派生密钥能保证密钥长度符合AES的要求,同时比直接补位更安全。
  • 解密时加入异常捕获,可以更友好地处理密钥错误、数据篡改等问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:54:29