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

socket.io传输加密数据后WebCrypto AES-GCM解密返回DOMException问题

Socket.IO转发AES加密二进制数据报错问题解决方案

核心原因

  • 类型变化:Socket.IO默认序列化逻辑不保留TypedArray类型信息,发送Uint8Array类型的iv时,会自动提取其底层的ArrayBuffer作为二进制帧传输,因此客户端2收到的iv为ArrayBuffer类型,属于框架正常行为。
  • 二进制内容错乱:当单次发送的对象包含多个独立ArrayBuffer字段时,Socket.IO的二进制自动拆分重组逻辑容易出现字段映射错位,导致接收端拿到的iv、加密消息的二进制内容与发送端不一致,最终触发AES-GCM解密的DOMException错误。

解决方案

方案1:Base64编码传输(推荐,兼容性最高)

将二进制内容转换为字符串传输,彻底规避Socket.IO的二进制处理逻辑问题:

客户端1发送逻辑修改

let encryptedData = await encrypt(text);
// 加密消息转base64
const messageBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedData.message)));
// iv转base64
const ivBase64 = btoa(String.fromCharCode(...encryptedData.iv));
socket.emit('message', { message: messageBase64, iv: ivBase64 });

客户端2接收逻辑修改

socket.on('answer', async function(answer){
  // base64转回对应二进制格式
  const message = Uint8Array.from(atob(answer.message), c => c.charCodeAt(0)).buffer;
  const iv = Uint8Array.from(atob(answer.iv), c => c.charCodeAt(0));
  let decryptedData = await decrypt(message, iv);
});

方案2:合并二进制传输(性能更高)

将iv和加密消息合并为单个ArrayBuffer传输,避免多二进制字段的映射错误:

客户端1发送逻辑修改

let encryptedData = await encrypt(text);
const msgUint8 = new Uint8Array(encryptedData.message);
// 前12位存iv,后续存加密消息
const combined = new Uint8Array(12 + msgUint8.length);
combined.set(encryptedData.iv, 0);
combined.set(msgUint8, 12);
socket.emit('message', combined.buffer);

客户端2接收逻辑修改

socket.on('answer', async function(combinedBuffer){
  // 按偏移量拆分iv和加密消息
  const iv = new Uint8Array(combinedBuffer, 0, 12);
  const message = new Uint8Array(combinedBuffer, 12).buffer;
  let decryptedData = await decrypt(message, iv);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:09:01