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

Crypto.js与pycrypto的AES加密结果不一致,如何实现跨语言兼容?

AES跨语言(CryptoJS vs pycrypto)兼容问题解决

问题背景

在Node.js环境使用CryptoJS的AES算法加密文本,JS内加解密正常;Python用pycrypto实现相同逻辑,Python内加解密也正常,但JS生成的密文无法在Python解密,核心原因是双方加密结果不一致。

JS侧实现代码

import CryptoJS from "crypto-js";

let str = "lol";
let salt = "ABCDEFGHIJKLMNOP";
let key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP";

salt = CryptoJS.enc.Hex.parse(salt);
key = CryptoJS.enc.Hex.parse(key);

const options = {
  iv: salt,
  padding: CryptoJS.pad.ZeroPadding,
  mode: CryptoJS.mode.CFB,
};

// 加密函数
function encrypt(str, salt, key) {
  const cipher = CryptoJS.AES.encrypt(str, key, options);
  console.log("cipher", CryptoJS.enc.Hex.stringify(cipher.ciphertext));
  return cipher.ciphertext.toString(CryptoJS.enc.Base64);
}

// 解密函数
function decrypt(str, salt, key) {
  const cipher = CryptoJS.AES.decrypt(str, key, options);
  return cipher.toString(CryptoJS.enc.Utf8);
}

const encrypted = encrypt(str, salt, key);
console.log("encrypted", encrypted);

const decrypted = decrypt(encrypted, salt, key);
console.log("decrypted", decrypted);

// 输出
// encrypted sd4Xpz/ws8x2j+cgF17t6A==
// decrypted lol

Python侧原实现代码

from Crypto.Cipher import AES
from base64 import b64encode, b64decode

str = "lol";
salt = b"ABCDEFGHIJKLMNOP";
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP";
enc_dec_method = 'utf-8'


def encrypt(str_to_enc, str_key, salt):
    aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, salt)
    hx_enc = aes_obj.encrypt(str_to_enc.encode('utf8'))
    mret = b64encode(hx_enc).decode(enc_dec_method)
    return mret

def decrypt(str_to_dec, str_key, salt):
    aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, salt)
    str_tmp = b64decode(str_to_dec.encode(enc_dec_method))
    str_dec = aes_obj.decrypt(str_tmp)
    mret = str_dec.decode(enc_dec_method)
    return mret

test_enc_text = encrypt(str, key, salt)
test_dec_text = decrypt(test_enc_text, key, salt)

print(f"Encrypted Text: {test_enc_text}")
print(f"Decrypted Text: {test_dec_text}")

# 输出
# Encrypted Text: o9XB
# Decrypted Text: lol

已尝试的排查步骤

  • 分别验证两种语言内的加解密功能正常
  • 查阅两个库的官方文档与源码
  • 排查编码/解码环节问题,未找到原因

关键差异点与解决方案

1. 密钥与IV的解析方式不一致

JS侧使用CryptoJS.enc.Hex.parse()将字符串解析为十六进制字节,而Python侧直接将字符串按UTF-8编码为字节,导致双方实际使用的密钥、IV二进制数据完全不同。

  • 修正:Python侧需用binascii.unhexlify()将原字符串按十六进制解析为字节,和JS侧对齐。

2. CFB模式的段大小(Segment Size)不同

CryptoJS的CFB模式默认使用128位段大小(与AES块大小一致),而pycrypto的AES.MODE_CFB默认使用8位段大小,这是加密结果差异的核心原因。

  • 修正:Python初始化AES对象时,指定segment_size=128,和CryptoJS对齐。

3. 填充方式的冗余设置

CFB模式属于流密码模式,本身不需要填充,JS侧设置的ZeroPadding不会生效(因为CryptoJS在流模式下会忽略填充配置),Python侧也无需额外设置填充,这点不影响当前场景,但需明确流模式的特性。

修正后的Python代码

from Crypto.Cipher import AES
from base64 import b64encode, b64decode
import binascii

str = "lol"
# 按十六进制解析salt,与JS侧CryptoJS.enc.Hex.parse()对齐
salt = binascii.unhexlify("ABCDEFGHIJKLMNOP")
# 按十六进制解析key,与JS侧对齐
key = binascii.unhexlify("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
enc_dec_method = 'utf-8'

def encrypt(str_to_enc, str_key, salt):
    # 指定CFB段大小为128位,匹配CryptoJS默认值
    aes_obj = AES.new(str_key, AES.MODE_CFB, salt, segment_size=128)
    hx_enc = aes_obj.encrypt(str_to_enc.encode(enc_dec_method))
    mret = b64encode(hx_enc).decode(enc_dec_method)
    return mret

def decrypt(str_to_dec, str_key, salt):
    aes_obj = AES.new(str_key, AES.MODE_CFB, salt, segment_size=128)
    str_tmp = b64decode(str_to_dec.encode(enc_dec_method))
    str_dec = aes_obj.decrypt(str_tmp)
    mret = str_dec.decode(enc_dec_method)
    return mret

test_enc_text = encrypt(str, key, salt)
test_dec_text = decrypt(test_enc_text, key, salt)

print(f"Encrypted Text: {test_enc_text}")
print(f"Decrypted Text: {test_dec_text}")

修正后,Python生成的密文与JS侧一致:sd4Xpz/ws8x2j+cgF17t6A==,且能正常解密JS生成的密文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:15:34