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

Node.js中WhatsApp Flows解密报错:RangeError: Invalid key length

WhatsApp Flow 端点解密/加密实现(解决Invalid key length错误)

问题场景

使用Node.js解密WhatsApp Flow加密数据时,触发crypto.createDecipheriv的Invalid key length错误,需完整实现请求解密与响应加密逻辑。

加密数据

{
  "encrypted_flow_data": "EfdsCol+ZQMdkWYaa+cB247XRCfTbMkfdwR68ZwU1pQgby4P8tR2l7qDDjh/uLCkzutO0GuMQxoVfm/sluoj4OuMzsd9AttTerts4vcvaDWrbBcXpH5r3m4vu6iNwTQHV4kmL2sETB1g22VbEA==",
  "encrypted_aes_key": "A01kXb7211vxwfZbSlxN9fxL/HUWBhxjVovJ6jirVzUYK7CYLnlcBoR4AwIWIiP3NSra8DRvVd9gulu+jdDJEbf+8HZHk1k5EllcSFV/r/x1PLwpQ6v8AeOhbfEp8qyjSxb3Ah6/CrY6oDWDLiyqpAWz3KK4UmWw9VxiJOHdLhvfa3lH22zwReboiJyUPFbjKlzKUudnS8EI5JU+ZUW3reEOB5JS8bMJ06asHYm723VUvC3cs8qv1/G02NPlOo3G9sknDSr3fo0uIm5drvq3flLW6Mvcx469Y97x3j44RjEIyXMIs8zUyOo5h9MrTuwruPsjhcBFIByDHH7wwTMPQw==",
  "initial_vector": "oqVIt/A7/MWVY4hE9IHb6A=="
}

原代码核心问题

  1. 私钥异步读取未等待结果,直接传入解密函数导致变量未赋值
  2. 私钥变量名前后不一致(privateKeyPEM vs privateKeyPem)
  3. AES密钥做了冗余的Base64编码/解码操作,破坏原始密钥长度
  4. 定义了IV翻转函数但未实际使用,不符合WhatsApp Flow要求
  5. 未处理异步操作的错误捕获

修复后的请求解密代码

const crypto = require('crypto');
const fs = require('fs').promises; // 使用Promise版文件操作

// 翻转IV字节顺序(WhatsApp Flow强制要求)
function flipIV(ivBuffer) {
  return Buffer.from(ivBuffer.reverse());
}

async function decryptFlowRequest(reqBody) {
  try {
    // 1. 解析请求参数
    const { encrypted_flow_data, encrypted_aes_key, initial_vector } = reqBody;

    // 2. 读取并加载私钥
    const privateKeyPem = await fs.readFile('/path/to/your/private_key.pem', 'utf-8');
    const privateKey = crypto.createPrivateKey({
      key: privateKeyPem,
      format: 'pem'
    });

    // 3. RSA-OAEP-SHA256解密AES密钥
    const encryptedAesKey = Buffer.from(encrypted_aes_key, 'base64');
    const aesKey = crypto.privateDecrypt({
      key: privateKey,
      oaepHash: 'sha256',
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    }, encryptedAesKey);

    // 4. 处理IV(翻转字节)
    const iv = flipIV(Buffer.from(initial_vector, 'base64'));

    // 5. AES-256-GCM解密Flow数据
    const encryptedFlowData = Buffer.from(encrypted_flow_data, 'base64');
    // 分离密文与16字节GCM认证标签
    const ciphertext = encryptedFlowData.slice(0, -16);
    const authTag = encryptedFlowData.slice(-16);

    const decipher = crypto.createDecipheriv('aes-256-gcm', aesKey, iv);
    decipher.setAuthTag(authTag);

    let decrypted = decipher.update(ciphertext);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    return JSON.parse(decrypted.toString('utf-8'));
  } catch (err) {
    console.error('解密失败:', err);
    throw err;
  }
}

// Express路由使用示例
// app.post('/flow-endpoint', async (req, res) => {
//   const decryptedData = await decryptFlowRequest(req.body);
//   console.log('解密后的请求数据:', decryptedData);
//   // 业务逻辑处理...
// });

响应加密实现

// 加载WhatsApp提供的公钥(用于加密AES密钥)
async function loadWhatsAppPublicKey() {
  const publicKeyPem = await fs.readFile('/path/to/whatsapp_public_key.pem', 'utf-8');
  return crypto.createPublicKey({
    key: publicKeyPem,
    format: 'pem'
  });
}

async function encryptFlowResponse(responseData, waPublicKey) {
  try {
    // 1. 生成随机AES-256密钥和12字节IV(GCM推荐长度)
    const aesKey = crypto.randomBytes(32);
    const iv = crypto.randomBytes(12);
    const flippedIv = flipIV(iv); // 翻转IV字节

    // 2. AES-256-GCM加密响应数据
    const cipher = crypto.createCipheriv('aes-256-gcm', aesKey, iv);
    let encryptedData = cipher.update(JSON.stringify(responseData), 'utf-8');
    encryptedData = Buffer.concat([encryptedData, cipher.final()]);
    const authTag = cipher.getAuthTag();

    // 拼接密文与认证标签
    const encryptedFlowData = Buffer.concat([encryptedData, authTag]);

    // 3. RSA-OAEP-SHA256加密AES密钥
    const encryptedAesKey = crypto.publicEncrypt({
      key: waPublicKey,
      oaepHash: 'sha256',
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    }, aesKey);

    // 4. 返回符合格式的加密响应
    return {
      encrypted_flow_response: encryptedFlowData.toString('base64'),
      encrypted_aes_key: encryptedAesKey.toString('base64'),
      initial_vector: flippedIv.toString('base64')
    };
  } catch (err) {
    console.error('加密失败:', err);
    throw err;
  }
}

// Express路由使用示例
// app.post('/flow-endpoint', async (req, res) => {
//   const decryptedData = await decryptFlowRequest(req.body);
//   // 业务逻辑处理,生成响应数据
//   const responseData = { status: 'success', data: { /* 自定义响应内容 */ } };
//   const waPublicKey = await loadWhatsAppPublicKey();
//   const encryptedResponse = await encryptFlowResponse(responseData, waPublicKey);
//   res.json(encryptedResponse);
// });

关键注意事项

  • IV翻转: 必须对初始向量执行字节翻转操作,否则解密/加密会失败
  • 密钥长度: AES-256要求32字节密钥,直接使用RSA解密后的原始Buffer,避免冗余编码
  • 异步处理: 所有文件读取、加密解密操作需用异步逻辑,避免阻塞事件循环
  • 错误捕获: 必须捕获加密解密过程中的异常,防止服务崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:58:10