You need to enable JavaScript to run this app. 如何在Python中解密旧版OpenSSL 3DES加密数据以完成MySQL迁移
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中解密旧版OpenSSL 3DES加密数据以完成MySQL迁移

OpenSSL enc 带盐格式结构拆解

Base64解码后得到的Salted__开头字节串,是OpenSSL enc命令默认的带盐加密格式,结构固定为:

  • 前8字节:固定ASCII标识Salted__,无实际加密作用
  • 紧随的8字节:随机盐值,用于派生密钥时削弱彩虹表攻击风险
  • 剩余全部字节:3DES-CBC模式的实际密文
密钥与IV的派生逻辑

现有解密命令openssl enc -des3 -md md5 -a -A -pass pass:<PASSPHRASE> -d对应的派生逻辑,完全遵循OpenSSL内部EVP_BytesToKey规则,无额外黑盒:

  1. 从解码的字节串中提取8字节盐值(跳过开头的Salted__标识位)
  2. 3DES加密需要24字节密钥、CBC模式需要8字节初始化向量(IV),共需凑集32字节派生材料
  3. 派生计算流程:
    • 第一轮:计算MD5摘要,输入内容为「密码短语原始字节 + 提取到的8字节盐值」,得到16字节摘要块
    • 第二轮:因单轮MD5仅输出16字节,未达到32字节的总需求,继续计算MD5摘要,输入内容为「上一轮的16字节摘要块 + 密码短语原始字节 + 提取到的8字节盐值」,再得到16字节摘要块
    • 拼接两轮摘要块为32字节总派生材料:前24字节为3DES密钥,后8字节为CBC模式IV
无系统命令依赖的Python解密实现

基于cryptography库实现的解密逻辑,与OpenSSL命令解密结果完全一致:

import base64
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

# 替换为实际业务值
ENCODED_DATA = "旧库中存储的Base64加密串"
PASSPHRASE = b"旧系统使用的加密密码短语"

# Base64解码原始存储内容
decoded_raw = base64.b64decode(ENCODED_DATA)
# 校验OpenSSL带盐格式
if not decoded_raw.startswith(b"Salted__"):
    raise ValueError("存储内容不符合OpenSSL带盐加密格式")
# 拆分盐值与密文
salt = decoded_raw[8:16]
ciphertext = decoded_raw[16:]

# 按OpenSSL规则派生密钥与IV
derived_material = b""
previous_digest = b""
required_derived_len = 32  # 24字节3DES密钥 + 8字节CBC IV
while len(derived_material) < required_derived_len:
    md5 = hashes.Hash(hashes.MD5(), backend=default_backend())
    md5.update(previous_digest + PASSPHRASE + salt)
    current_digest = md5.finalize()
    derived_material += current_digest
    previous_digest = current_digest
# 拆分密钥与IV
key = derived_material[:24]
iv = derived_material[24:32]

# 3DES-CBC解密
cipher = Cipher(algorithms.TripleDES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize()

# 移除OpenSSL默认的PKCS#7填充
padding_length = padded_plaintext[-1]
plaintext = padded_plaintext[:-padding_length]
落地注意事项
  • 密码短语编码需与旧系统完全匹配:如果旧系统使用GBK/GB2312编码存储密码,不要强制转成UTF-8,否则派生密钥会完全错误
  • 模式匹配:旧OpenSSL的des3参数默认对应3DES-EDE-CBC模式,与cryptography库的TripleDES默认行为完全一致,无需额外调整
  • 库兼容性:如果选择使用oscrypto而非cryptography,上述密钥、IV的派生逻辑完全通用,仅需替换对应的解密接口调用即可
  • 现代加密迁移:解密得到明文后,直接使用AES-256-GCM等现代加密算法重新加密存储即可,无需沿用旧的3DES+MD5弱加密逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 02:36:03