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

Python中AES/CBC/PKCS5填充问题:在线解密结果含乱码

AES-256-CBC加密后在线解密出现乱码的问题排查与解决

问题描述

  • 用Python实现AES-256-CBC加密,输入内容为164386,加密后输出密文:MTIzZWRmcjRAIzkwJjY1JES7OMmdSrtGJX+An1UoVNY=
  • 使用在线解密工具时,得到的结果为öÁéáfsÊaׇÒH164386,而非预期的原输入164386

相关参数

  • 密钥长度:256位
  • 加密模式:CBC
  • IV值:b'123edfr4@#90&65$'(16字节,符合AES块大小要求)
  • 填充方式:PKCS7

原始加密代码

import base64
from Crypto.Cipher import AES
from Crypto.Cipher import AES as cryptoAES
from base64 import b64decode
from base64 import b64encode


class Globals:
    def __init__(self):
        self.KEY = b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        self.IV = b'123edfr4@#90&65$'


BS = cryptoAES.block_size
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]


class AESCipher:
    def __init__(self):
        self.key = b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        self.iv = b'123edfr4@#90&65$'
        
    def encrypt(self, data):
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        _pad = pad(data).encode('utf-8')
        response = base64.b64encode(self.iv + cipher.encrypt(_pad)).decode('utf-8')
        print('+++++++++++',response)


def test():
    app_id = '164386'
    response = AESCipher().encrypt(app_id)
    return response

output = test()

问题根源

你的加密代码将IV与加密后的密文拼接在一起,再进行Base64编码,但在线解密工具默认会把你输入的整个Base64解码结果当作「纯密文」处理。当工具用指定的IV解密这个拼接内容时:

  1. 前16字节(原IV)会被当作第一个密文块,解密后与设置的IV异或,产生乱码
  2. 后面的真实密文块解密后,与前一个块(原IV)异或,得到正确的原内容
    最终结果就会出现「前16字节乱码+正确明文」的情况。

解决方案

方案1:适配在线工具解密(无需修改代码)

  1. 对加密输出的Base64字符串MTIzZWRmcjRAIzkwJjY1JES7OMmdSrtGJX+An1UoVNY=进行解码,得到字节串
  2. 分离出前16字节(原IV)和后面的真实密文
  3. 将分离出的真实密文重新进行Base64编码,作为在线工具的「密文」输入
  4. 在在线工具中手动填入IV值:123edfr4@#90&65$
  5. 其他参数设置:
    • 密钥:填入你的32字节密钥(XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX对应的真实值)
    • 加密模式:CBC
    • 填充方式:PKCS7
    • 输出格式:UTF-8

方案2:修改加密代码,输出纯密文Base64(推荐)

如果不需要把IV和密文拼接传输,可以调整加密逻辑,只输出密文的Base64编码,IV单独存储或传递:

import base64
from Crypto.Cipher import AES

BS = AES.block_size
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]


class AESCipher:
    def __init__(self):
        self.key = b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        self.iv = b'123edfr4@#90&65$'
        
    def encrypt(self, data):
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        padded_data = pad(data).encode('utf-8')
        ciphertext = cipher.encrypt(padded_data)
        # 仅输出密文的Base64编码,IV可单独返回或存储
        return base64.b64encode(ciphertext).decode('utf-8')
        
    def decrypt(self, ciphertext_b64):
        ciphertext = base64.b64decode(ciphertext_b64)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        padded_plaintext = cipher.decrypt(ciphertext)
        return unpad(padded_plaintext.decode('utf-8'))


def test():
    app_id = '164386'
    ciphertext = AESCipher().encrypt(app_id)
    print('加密结果:', ciphertext)
    # 测试解密
    plaintext = AESCipher().decrypt(ciphertext)
    print('解密结果:', plaintext)
    return ciphertext

output = test()

额外优化点

  • 移除了代码中重复导入的AES和base64模块
  • 新增了解密方法,方便本地验证加密结果的正确性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:15:32