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

Python与JavaScript AES加密结果不一致的问题及解决方法

JS与Python AES-CBC加密结果不一致的解决办法

你这两段代码结果不一致的核心原因很明确,直接看问题和修复方案:

问题根源

  • JS代码搞反了加密和解密:你定义的是encryptSeed加密函数,但内部却使用了crypto.createDecipheriv(这是解密专用函数),完全颠倒了操作逻辑,自然不可能和Python的加密结果匹配。
  • 密文处理方式错误:两段代码最后都尝试将二进制密文直接用UTF-8解码,这大概率会失败——密文是随机二进制数据,无法直接转成合法的UTF-8字符串,通常用十六进制或Base64编码输出才是正确做法。

修复后的代码

修正后的JavaScript代码

import crypto from 'crypto';

function encryptSeed(text, key, iv) {
    const keyBuffer = Buffer.from(key, "utf8");
    console.log("key:" + keyBuffer.toString("hex"));
    const ivBuffer = Buffer.from(iv, "utf8");
    console.log("iv:" + ivBuffer.toString("hex"));
    // 若text是明文,替换为Buffer.from(text, "utf8"),此处保留原代码的十六进制输入逻辑
    const textBuffer = Buffer.from(text, "hex");
    console.log("text:" + textBuffer.toString("hex"));
    
    // 替换为加密专用的createCipheriv,算法保持aes-128-cbc
    const cipher = crypto.createCipheriv("aes-128-cbc", keyBuffer, ivBuffer);
    let encrypted = cipher.update(textBuffer);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    console.log("result:" + encrypted.toString("hex"));
    
    // 返回十六进制编码的密文,避免UTF-8解码失败
    return encrypted.toString("hex");
}

修正后的Python代码

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def encrypt_seed(text, key, iv):
    key_bytes = key.encode("utf8")
    print("key:" + key_bytes.hex())
    iv_bytes = iv.encode("utf8")
    print("iv:" + iv_bytes.hex())
    text_bytes = bytes.fromhex(text)
    print("text:" + text_bytes.hex())
    
    cryptor = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
    # 显式执行PKCS7填充,和Node.js默认行为对齐,避免版本差异
    padded_text = pad(text_bytes, AES.block_size)
    ciphertext = cryptor.encrypt(padded_text)
    print("result:" + ciphertext.hex())
    
    # 返回十六进制编码的密文
    return ciphertext.hex()

额外注意事项

  • 密钥长度要求:aes-128-cbc要求密钥必须是16字节(128位),确保传入的key字符串转成UTF-8后正好是16字节——否则Node.js会自动截断密钥,PyCryptodome则会直接抛出错误。
  • IV长度要求:CBC模式的IV必须与块大小一致(16字节),两段代码均使用UTF-8转码,要保证iv字符串转成字节后长度为16字节。
  • 填充一致性:Node.js的createCipheriv默认使用PKCS7填充,PyCryptodome的encrypt在明文长度非块倍数时也默认使用PKCS7,但显式调用pad函数可以避免不同版本的行为差异。
  • 输出编码规范:密文属于二进制数据,不要直接尝试用UTF-8解码,推荐用十六进制或Base64编码后返回,这样在不同语言间传递更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:13:13