Python Socket AES256加密后,JS接收ArrayBuffer解密失败求助
Python AES-256 Socket加密 + JS Crypto-JS解密 修复方案
嘿,我一看你这代码就知道问题出在哪了——两端的加密解密参数完全没对齐,导致解密后拿不到有效数据。我给你拆解下问题,再直接上修复后的代码:
核心问题分析
- Python端没做PKCS7填充:你JS端解密用的是
Pkcs7padding,但Python加密时注释掉了填充逻辑,当明文长度不是16字节(AES块大小)的整数倍时,加密出来的内容本身就有问题,解密自然失败。 - JS端硬编码了IV:Python加密时生成了随机IV,还把IV和密文拼接在一起发送了,但你JS端却用全0的IV去解密,这完全不匹配,肯定解不出东西。
- Base64处理错误:Python发送的是Base64编码后的字节,但你JS端直接把ArrayBuffer转成WordArray,相当于处理的是Base64字符串的原始字节,而不是真正的加密数据。
修复后的Python代码
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad import hashlib import base64 class AES_256(object): def __init__(self, key): self.bs = AES.block_size # 用SHA256生成32字节的AES-256密钥,和JS端逻辑对齐 self.key = hashlib.sha256(key.encode("utf-8")).digest() def encrypt(self, raw): # 统一处理明文:字符串转字节,然后做PKCS7填充 if isinstance(raw, str): raw = raw.encode('utf-8') padded_raw = pad(raw, self.bs) # 生成随机IV(必须和密文一起发送,JS端要用来解密) iv = get_random_bytes(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) # 拼接IV和密文,再Base64编码后发送 encrypted_data = iv + cipher.encrypt(padded_raw) return base64.b64encode(encrypted_data) # 示例:加密并准备发送数据 encryption_256 = AES_256("password") buffer = "你要发送的原始数据,可以是字符串或字节" encrData = encryption_256.encrypt(buffer) # 这里直接把encrData通过Socket发送即可(它已经是bytes类型)
修复后的JavaScript代码
// 接收Socket传来的ArrayBuffer并解密 function decryptSocketData(arrayBuffer, password) { // 1. 把ArrayBuffer转成UTF-8字符串(Python发的是Base64编码的ASCII串) const base64Str = new TextDecoder('utf-8').decode(arrayBuffer); // 2. Base64解码,得到包含IV和密文的二进制数据 const encryptedData = CryptoJS.enc.Base64.parse(base64Str); // 3. 提取IV(前16字节,AES块大小)和密文(剩下的部分) const iv = CryptoJS.lib.WordArray.create(encryptedData.words.slice(0, 4), 16); const ciphertext = CryptoJS.lib.WordArray.create( encryptedData.words.slice(4), encryptedData.sigBytes - 16 ); // 4. 生成和Python端一致的AES密钥 const key = CryptoJS.SHA256(password); // 5. 解密,参数和Python端完全对齐 const decrypted = CryptoJS.AES.decrypt( { ciphertext: ciphertext }, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); // 6. 转成UTF-8字符串返回 return decrypted.toString(CryptoJS.enc.Utf8); } // 示例使用:假设encodedFrame.data是Socket接收的ArrayBuffer const decryptedResult = decryptSocketData(encodedFrame.data, "password"); console.log("解密后的数据:", decryptedResult);
关键修复点说明
- 填充对齐:Python端新增
pad处理,和JS端的Pkcs7padding完全匹配,解决明文长度不兼容的问题。 - IV动态提取:不再硬编码IV,而是从加密数据中取出Python生成的随机IV,保证解密时参数一致。
- Base64正确解码:先把ArrayBuffer转成Base64字符串再解码,拿到真正的加密内容,而不是处理Base64的原始字节。
- 密钥生成简化:JS端直接用
CryptoJS.SHA256(password)生成密钥,和Python端的SHA256处理逻辑完全一致,无需额外转码。
内容的提问来源于stack exchange,提问作者CodeDezk
相关产品推荐
相关产品推荐

