Node.js加密API响应后React.js解密遇UTF-8格式错误求助
解决AES解密时的"Malformed UTF-8 data"错误
问题根源分析
你的代码存在三个核心问题,直接导致了解密失败:
环境判断逻辑完全颠倒
两端的isProduction都写成了判断环境等于development,这意味着生产环境下实际走的是不加密/不解密逻辑,反而在开发环境启用加密解密,完全违背了设计初衷。CryptoJS未正确识别Hex格式密文
Node.js端输出的是Hex编码的密文,但CryptoJS的AES.decrypt默认将输入视为Base64格式,直接传入Hex字符串会导致解密出错误的二进制数据,转换为UTF-8时自然抛出"Malformed UTF-8 data"错误。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); };
验证步骤
- 确认生产环境下
process.env.NODE_ENV(Node.js)和VITE_NODE_ENV(React)均被正确设置为production - 测试时可临时将
isProduction强制设为true,验证加密解密逻辑是否正常运行 - 检查解密后的字符串是否为有效JSON,避免后续JSON解析报错
内容的提问来源于stack exchange,提问作者Vikas Yadav
相关产品推荐
相关产品推荐

