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

CryptoJS AES-CBC加盐解密转Python后解密失败问题排查

CryptoJS AES-CBC加盐解密转Python的问题排查与解决

问题背景

现有一段基于CryptoJS的JavaScript AES-CBC加盐解密逻辑,需要改写为Python版本,但Python代码处理密钥时得到错误的解密结果,且无法修改原有加密方式,只能调整Python解密逻辑。

原代码对比

JavaScript代码

// y is array with all data
var decryptjson = {"ct": y[0].substr(2), "iv": y[1], "s": y[2]}
var cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(decryptjson.ct)
});
if (decryptjson.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(decryptjson.iv);
if (decryptjson.s) cipherParams.salt = CryptoJS.enc.Hex.parse(decryptjson.s);
var a = CryptoJS.AES.decrypt(cipherParams, key).toString(CryptoJS.enc.Utf8)

原Python代码

decryptdict = {"ct":y[0], "iv": y[1], "s": y[2]}
ct = b64decode(decryptdict["ct"])
iv = bytes.fromhex(decryptdict["iv"])
salt = bytes.fromhex(decryptdict["s"])
key = pbkdf2.PBKDF2(key, salt).read(32)
cipher = AES.new(key, AES.MODE_CBC, iv)
decryptedstring = cipher.decrypt(ct)

问题排查

  1. 密文预处理不一致
    JS代码中对密文做了y[0].substr(2)操作(去掉前两位字符),但原Python代码直接使用y[0],导致密文数据不匹配。

  2. 密钥派生算法错误
    CryptoJS的AES.decrypt在传入salt时,默认使用OpenSSL的EVP_BytesToKey算法(基于MD5哈希、1次迭代),而非PBKDF2。原Python代码误用PBKDF2生成密钥,导致密钥与JS端不一致,这是解密失败的核心原因。

  3. 填充未处理
    CryptoJS默认使用PKCS7填充,原Python代码解密后未去除填充字节,会导致结果末尾出现多余的乱码字符。

修正后的Python代码

from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Hash import MD5
from Crypto.Util.Padding import unpad

# 替换为实际的y数组数据
y = ["你的密文字符串", "IV的十六进制值", "盐的十六进制值"]
# 密文需去掉前两位,和JS逻辑对齐
decryptdict = {"ct": y[0][2:], "iv": y[1], "s": y[2]}
# 替换为JS端使用的原始密钥
password = b"your_original_key"

ct = b64decode(decryptdict["ct"])
iv = bytes.fromhex(decryptdict["iv"])
salt = bytes.fromhex(decryptdict["s"])

# 实现CryptoJS默认的EVP_BytesToKey密钥派生逻辑
def evp_bytes_to_key(password, salt, key_len=32, iv_len=16):
    buf = b""
    while len(buf) < key_len + iv_len:
        md5_hash = MD5.new()
        md5_hash.update(buf + password + salt)
        buf += md5_hash.digest()
    key = buf[:key_len]
    return key

# 生成匹配的密钥
key = evp_bytes_to_key(password, salt)
# 初始化CBC解密器
cipher = AES.new(key, AES.MODE_CBC, iv)
# 解密并去除PKCS7填充
decrypted_bytes = cipher.decrypt(ct)
decryptedstring = unpad(decrypted_bytes, AES.block_size).decode("utf-8")

print(decryptedstring)

说明

  • 确保安装依赖:执行pip install pycryptodome
  • 代码中需替换y数组、password为实际业务数据
  • 密钥派生逻辑严格对齐CryptoJS的默认行为,保证密钥一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:25:40