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

Node.js加密API响应后React.js解密遇UTF-8格式错误求助

解决AES解密时的"Malformed UTF-8 data"错误

问题根源分析

你的代码存在三个核心问题,直接导致了解密失败:

  1. 环境判断逻辑完全颠倒
    两端的isProduction都写成了判断环境等于development,这意味着生产环境下实际走的是不加密/不解密逻辑,反而在开发环境启用加密解密,完全违背了设计初衷。

  2. CryptoJS未正确识别Hex格式密文
    Node.js端输出的是Hex编码的密文,但CryptoJS的AES.decrypt默认将输入视为Base64格式,直接传入Hex字符串会导致解密出错误的二进制数据,转换为UTF-8时自然抛出"Malformed UTF-8 data"错误。

  3. React端变量重复声明
    解密函数内部重新声明了iv变量,虽然不影响功能,但容易造成逻辑混淆。

修复后的代码

Node.js端加密代码

import crypto from 'crypto';
// 修正环境判断:仅生产环境启用加密
const isProduction = process.env.NODE_ENV === 'production';
const algorithm = 'aes-256-cbc';
const encryptionKey = isProduction
  ? Buffer.from('ce73fc57a80b6f7db56e16dd673ec9ebf8df9d35b648e9ac9bb353dd89772331', 'hex')
  : null;
const iv = isProduction
  ? Buffer.from('b86861bbb4753e9dd05675aab83a14ff', 'hex')
  : null;

const encrypt = (text) => {
  if (!isProduction || !encryptionKey || !iv) return text;
  const cipher = crypto.createCipheriv(algorithm, encryptionKey, iv);
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  return { iv: iv.toString('hex'), encryptedData: encrypted };
};

// 响应加密中间件
app.use((req, res, next) => {
  if (isProduction) {
    const originalJson = res.json;
    res.json = (body) => {
      const encryptedBody = encrypt(JSON.stringify(body));
      originalJson.call(res, encryptedBody);
    };
  }
  next();
});

React.js端解密代码

import CryptoJS from 'crypto-js';
import { VITE_NODE_ENV } from './config';

// 修正环境判断:仅生产环境启用解密
const isProduction: boolean = VITE_NODE_ENV === 'production';

const key = isProduction
  ? CryptoJS.enc.Hex.parse('ce73fc57a80b6f7db56e16dd673ec9ebf8df9d35b648e9ac9bb353dd89772331')
  : null;

const decrypt = (encryptedPayload: { iv: string; encryptedData: string }): Record<string, unknown> | null => {
  try {
    if (!isProduction || !key) return JSON.parse(encryptedPayload.encryptedData);

    // 解析接口返回的IV
    const payloadIv = CryptoJS.enc.Hex.parse(encryptedPayload.iv);
    // 关键:指定密文为Hex格式,匹配Node.js的加密输出
    const bytes = CryptoJS.AES.decrypt(encryptedPayload.encryptedData, key, {
      iv: payloadIv,
      format: CryptoJS.format.Hex
    });
    const decrypted = bytes.toString(CryptoJS.enc.Utf8);

    return JSON.parse(decrypted);
  } catch (error) {
    console.error('Decryption failed:', error);
    return null;
  }
};

export const getDecryptedResponse = (encryptedResponse: { iv: string; encryptedData: string }): Record<string, unknown> | null => {
  return decrypt(encryptedResponse);
};

验证步骤

  1. 确认生产环境下process.env.NODE_ENV(Node.js)和VITE_NODE_ENV(React)均被正确设置为production
  2. 测试时可临时将isProduction强制设为true,验证加密解密逻辑是否正常运行
  3. 检查解密后的字符串是否为有效JSON,避免后续JSON解析报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 12:51:06