Vite React前端向NestJS后端加密传输数据问题求助
解决方案:Vite React前端实现与NestJS后端兼容的RSA-OAEP加密
问题核心
Vite构建的前端运行在浏览器环境,无法直接使用Node.js专属的crypto模块;而crypto-js的RSA实现与Node.js crypto存在细节差异,导致后端无法解密。推荐使用浏览器原生Web Crypto API实现加密,其与Node.js crypto的RSA-OAEP实现对齐度更高,兼容性更好。
前端加密实现(Web Crypto API)
对应你原来的Node.js加密参数(RSA_PKCS1_OAEP_PADDING、SHA256),前端代码如下:
async function encryptData(json, publicKeyPem) { // 1. 解析PEM格式公钥:去除头尾标记和空白字符 const cleanedPem = publicKeyPem .replace(/-----BEGIN PUBLIC KEY-----/, '') .replace(/-----END PUBLIC KEY-----/, '') .replace(/\s+/g, ''); // 2. 将Base64编码的公钥转为ArrayBuffer const keyBuffer = Uint8Array.from(atob(cleanedPem), char => char.charCodeAt(0)); // 3. 导入公钥到Web Crypto,配置RSA-OAEP算法 const cryptoKey = await window.crypto.subtle.importKey( 'spki', // 公钥采用SPKI格式 keyBuffer, { name: 'RSA-OAEP', hash: 'SHA-256' }, false, // 公钥仅用于加密 ['encrypt'] ); // 4. 将JSON数据转为Uint8Array const dataBuffer = new TextEncoder().encode(JSON.stringify(json)); // 5. 执行加密 const encryptedBuffer = await window.crypto.subtle.encrypt( { name: 'RSA-OAEP' }, // OAEP标签留空,与Node.js默认行为一致 cryptoKey, dataBuffer ); // 6. 将加密结果转为Base64字符串,方便网络传输 return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))); }
后端解密(保持原有Node.js代码)
前端传输过来的是Base64字符串,后端只需先转成Buffer再解密即可:
const crypto = require('crypto'); function decryptData(encryptedBase64, privateKeyPem, passphrase) { const encryptedBuffer = Buffer.from(encryptedBase64, 'base64'); const decryptedBuffer = crypto.privateDecrypt( { key: privateKeyPem, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256', passphrase, // 私钥的密码 }, encryptedBuffer ); return JSON.parse(decryptedBuffer.toString()); }
为什么crypto-js无法兼容?
crypto-js的RSA-OAEP实现与Node.js crypto存在底层细节差异:
- 密钥解析逻辑不同,尤其是对带密码的密钥处理
- padding的具体实现细节不一致
- 哈希算法的调用链存在差异
这些差异会导致加密后的密文格式不匹配,后端无法解密。Web Crypto API是W3C标准规范,与Node.js crypto的RSA-OAEP实现遵循同一标准,兼容性更可靠。
内容的提问来源于stack exchange,提问作者Mohamad Zbib
相关产品推荐
相关产品推荐

