Node与Python间AES加密解密互操作填充错误排查
Node.js AES加密后Python解密失败问题排查
Node.js AES密钥生成代码
const generateAesKey = () => { const { randomBytes } = require('node:crypto'); randomBytes(32, (err, buf) => { if (err) throw err; return buf.toString('hex'); }); } const secretKey = generateAesKey();
密钥格式示例:491fb9719864f51e19a0705a3ef2de15cd91576d881cdc4bd4394bf7451ee404
Node.js AES加解密实现
const CryptoJS = require("crypto-js"); // 根据Tppaco的评论更新 const secretKey = CryptoJS.enc.Hex.parse("491fb9719864f51e19a0705a3ef2de15cd91576d881cdc4bd4394bf7451ee404"); const encrypt = (plainText) => { const iv = CryptoJS.enc.Utf8.parse('BBBBBBBBBBBBBBBB'); const encrypted = CryptoJS.AES.encrypt(plainText, CryptoJS.enc.Utf8.parse(secretKey), { iv: iv, mode: CryptoJS.mode.CBC, }); return encrypted.toString(); } const decrypt = (cipherText) => { const iv = CryptoJS.enc.Utf8.parse('BBBBBBBBBBBBBBBB'); const decrypted = CryptoJS.AES.decrypt(cipherText, CryptoJS.enc.Utf8.parse(secretKey), { iv: iv, mode: CryptoJS.mode.CBC, }); return CryptoJS.enc.Utf8.stringify(decrypted); } const en = encrypt("Text to be encrypted"); console.log(decrypt(en))
Node环境内加解密可正常运行,但将Node加密的数据拿到Python环境解密时出错。
Python端等效实现
from Crypto.Cipher import AES from Crypto.Util.Padding import pad,unpad import base64 import json import os # CBC模式+固定IV # key = os.urandom(32) # 生成随机密钥 # 根据Tppaco的评论更新 key = bytes.fromhex('491fb9719864f51e19a0705a3ef2de15cd91576d881cdc4bd4394bf7451ee404') data = 'Text to be encrypted' # 固定IV iv = 'BBBBBBBBBBBBBBBB'.encode('utf-8') # AES128需要16字节IV def encrypt(data,key,iv): data= pad(data.encode(),16) cipher = AES.new(key,AES.MODE_CBC,iv) return base64.b64encode(cipher.encrypt(data)) def decrypt(enc,key,iv): enc = base64.b64decode(enc) cipher = AES.new(key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(enc),16) def lambda_handler(event, context): encrypted = encrypt(data,key,iv) print('加密后的CBC base64字符串 : ',encrypted.decode("utf-8", "ignore")) decrypted = decrypt(encrypted,key,iv) print('解密后的数据: ', decrypted.decode("utf-8", "ignore")) return { 'statusCode': 200, 'decrypted text': json.dumps(decrypted.decode("utf-8", "ignore")) }
错误信息
"errorMessage": "Padding is incorrect.",
"errorType": "ValueError",
核心需求:实现Node加密、Python解密,请问哪里操作有误?
问题排查与修复
1. 密钥重复解析导致值错误
Node代码中,你已经用CryptoJS.enc.Hex.parse将十六进制密钥转换成了原始字节对象,但在加密和解密时又重复调用CryptoJS.enc.Utf8.parse(secretKey),这会把已转换好的字节对象再次当作UTF-8字符串解析,导致密钥实际值与Python端不匹配,最终触发解密填充错误。
修复方案:直接使用已解析好的secretKey,去掉多余的Utf8.parse:
// 加密函数修改 const encrypted = CryptoJS.AES.encrypt(plainText, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, }); // 解密函数修改 const decrypted = CryptoJS.AES.decrypt(cipherText, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, });
2. 密钥生成函数的异步问题
原generateAesKey使用异步的randomBytes,但直接返回会得到undefined(异步操作未完成),如果需要生成有效密钥,改成同步方式:
const generateAesKey = () => { const { randomBytes } = require('node:crypto'); const buf = randomBytes(32); return buf.toString('hex'); } const secretKey = generateAesKey();
3. 填充方式一致性验证
CryptoJS默认使用PKCS7填充,Python的pycryptodome中pad函数默认也是PKCS7填充(第二个参数为块大小,符合PKCS7规则),这部分无需修改,密钥修复后即可匹配。
修复后的完整Node代码
const CryptoJS = require("crypto-js"); const secretKey = CryptoJS.enc.Hex.parse("491fb9719864f51e19a0705a3ef2de15cd91576d881cdc4bd4394bf7451ee404"); const encrypt = (plainText) => { const iv = CryptoJS.enc.Utf8.parse('BBBBBBBBBBBBBBBB'); const encrypted = CryptoJS.AES.encrypt(plainText, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, }); return encrypted.toString(); } const decrypt = (cipherText) => { const iv = CryptoJS.enc.Utf8.parse('BBBBBBBBBBBBBBBB'); const decrypted = CryptoJS.AES.decrypt(cipherText, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, }); return CryptoJS.enc.Utf8.stringify(decrypted); } const en = encrypt("Text to be encrypted"); console.log("加密后字符串:", en); console.log("解密结果:", decrypt(en))
用修复后的Node代码加密得到的字符串,传入Python的decrypt函数即可正常解密,不会再出现填充错误。
内容的提问来源于stack exchange,提问作者micronyks
相关产品推荐
相关产品推荐

