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

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命令来匹配:

  1. 修改Python代码保存生成的IV(写入文件头部)
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:35:14