Python加密文件后用OpenSSL解密报Bad Magic Number错误求助
解决Python AES加密与OpenSSL解密不兼容的问题
问题根源
你的Python加密代码和OpenSSL命令存在几个关键不兼容点,导致出现bad magic number错误:
- OpenSSL默认使用带salt的自定义格式,你的代码直接输出Base64编码的原始密文,缺少该格式的头部标识
- 代码采用零填充规则,OpenSSL默认使用PKCS#7填充
- 代码未保存CBC模式必需的初始化向量(IV),OpenSSL需要IV才能完成解密
- OpenSSL的
-k参数是通过密码派生密钥,而非直接将传入的字符串作为密钥使用
修正后的Python加密代码
修改代码使其输出完全匹配OpenSSL默认格式(包含salt、IV,使用PKCS#7填充,输出二进制数据):
from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Random import get_random_bytes import hashlib def encrypt_file(input_path, output_path, password): # 生成OpenSSL默认的8字节随机salt salt = get_random_bytes(8) # 用OpenSSL的EVP_BytesToKey算法派生密钥和IV key_iv = hashlib.md5(password + salt).digest() # 针对256位密钥的派生逻辑 if len(password) > 16: key_iv += hashlib.md5(key_iv + password + salt).digest() key = key_iv[:32] iv = key_iv[32:48] # 读取明文并做PKCS#7填充 with open(input_path, 'rb') as f: plaintext = f.read() padded_plaintext = pad(plaintext, AES.block_size) # CBC模式加密 cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(padded_plaintext) # 按OpenSSL格式写入文件:Salted__标识 + salt + 密文 with open(output_path, 'wb') as outfile: outfile.write(b'Salted__' + salt + ciphertext) # 传入与原代码一致的密码字节串 password = b'0123456789abcdef0123456789abcdef' input_path = 'path/item_properties_part2/sample.csv' output_path = 'path/enc/sample.csv' encrypt_file(input_path, output_path, password)
对应的OpenSSL解密命令
现在可以直接用你最初的命令完成解密:
openssl aes-256-cbc -d -in path/enc/sample.csv -out decsample_final.csv -k 0123456789abcdef0123456789abcdef
可选:保留原加密逻辑的适配方案
如果一定要沿用你最初的加密逻辑,需要调整代码和OpenSSL命令来匹配:
- 修改Python代码保存生成的IV(写入文件头部)
- OpenSSL命令需要指定Base64解码、手动传入密钥和IV、事后去除零填充
修改后的Python代码
from Crypto.Cipher import AES import base64 from Crypto.Random import get_random_bytes def pad(s): return s + b"\0" * (AES.block_size - len(s) % AES.block_size) def encrypt_file(input_path, output_path, key): iv = get_random_bytes(AES.block_size) with open(input_path, 'rb') as f: plaintext = f.read() plaintext = pad(plaintext) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(plaintext) # 先写入IV,再写入Base64编码的密文 with open(output_path, 'wb') as outfile: outfile.write(iv + base64.b64encode(ciphertext)) key = b'0123456789abcdef0123456789abcdef' input_path = 'path/item_properties_part2/sample.csv' output_path = 'path/enc/sample.csv' encrypt_file(input_path, output_path, key)
对应的OpenSSL解密命令
# 提取文件头部16字节的IV并转为十六进制 IV_HEX=$(head -c 16 path/enc/sample.csv | xxd -p -c 16) # 提取剩余密文并解密,指定密钥和IV tail -c +17 path/enc/sample.csv | openssl aes-256-cbc -d -base64 -K $(echo -n '0123456789abcdef0123456789abcdef' | xxd -p) -iv $IV_HEX > decsample_final.csv # 去除末尾的零填充字节 truncate -s $(grep -ob "\x00*$" decsample_final.csv | head -n1 | cut -d: -f1) decsample_final.csv
内容的提问来源于stack exchange,提问作者Sharma
相关产品推荐
相关产品推荐

