Python解密AES-CBC分块加密文件遇16字节边界填充错误求助
解决AES-CBC解密的"Data must be padded to 16 byte boundary"错误
错误根源
- CBC链式逻辑被破坏:你拆分加密文件后单独解密每块,而CBC解密时每块的解密结果依赖前一块的密文作为初始向量(IV),每块都用原文件开头的IV完全不符合CBC的工作机制,必然导致块大小不匹配或解密失败。
- 未处理PKCS#7填充:OpenSSL默认使用PKCS#7填充规则,你的解密代码没有移除填充内容,即使块大小正确,最后也会残留无效填充字节;若拆分后最后一块不是16字节整数倍,直接触发边界错误。
- 密钥/IV格式错误:OpenSSL命令中的
-K和-iv参数是十六进制字符串,Python代码中必须将其转换为bytes类型,不能直接用字符串作为密钥。
正确解密实现
完整文件解密(推荐)
兼容OpenSSL AES-256-CBC规则,包含PKCS#7填充移除:
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad def decrypt_file(input_file_path, output_file_path, key_hex, iv_hex): # 把十六进制密钥、IV转为bytes key = bytes.fromhex(key_hex) iv = bytes.fromhex(iv_hex) with open(input_file_path, "rb") as input_file: ciphertext = input_file.read() cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext) # 移除PKCS#7填充 plaintext = unpad(plaintext, AES.block_size) with open(output_file_path, "wb") as output_file: output_file.write(plaintext)
大文件流式分块处理(不单独解密每块)
若文件过大需分块,必须保持CBC链式依赖,每块解密后更新IV为当前密文块:
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad def decrypt_large_file(input_file_path, output_file_path, key_hex, iv_hex): key = bytes.fromhex(key_hex) current_iv = bytes.fromhex(iv_hex) block_size = AES.block_size chunk_size = 1024 * block_size with open(input_file_path, "rb") as input_file, open(output_file_path, "wb") as output_file: while True: chunk = input_file.read(chunk_size) if not chunk: break cipher = AES.new(key, AES.MODE_CBC, current_iv) decrypted_chunk = cipher.decrypt(chunk) # 最后一块处理填充 if len(chunk) < chunk_size: decrypted_chunk = unpad(decrypted_chunk, block_size) output_file.write(decrypted_chunk) # 更新IV为当前密文块,供下一块解密使用 current_iv = chunk[-block_size:]
核心注意事项
- 禁止拆分加密文件单独解密:CBC是链式模式,单独解密每块会彻底破坏解密逻辑,导致块大小错误或内容乱码。
- 必须处理填充:OpenSSL默认使用PKCS#7填充,解密后必须用
unpad移除填充,否则会残留无效字节。 - 密钥/IV格式转换:OpenSSL的十六进制密钥、IV必须通过
bytes.fromhex()转为bytes才能用于AES解密。
内容的提问来源于stack exchange,提问作者Sharma
相关产品推荐
相关产品推荐

