Angular用node-forge RSA加密请求体,ASP.NET Core 6解密返回[object object]问题
RSA-OAEP加密解密异常:Angular(node-forge)加密后ASP.NET Core解密返回
[object object] 问题说明
在Angular中使用node-forge实现RSA-OAEP加密请求体,ASP.NET Core 6后端解密时无法获取正确明文,仅输出[object object],尝试通过PEM读取密钥未解决问题。
Angular端加密代码
import { Injectable } from '@angular/core'; import * as Forge from 'node-forge'; @Injectable({ providedIn: 'root', }) export class RSA { publicKey: string =`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArHQ09caWERhxf9deHJr2 AXwBUQuUdmjuZRRTAvkx+VkytEdycTgt8wNR53jjCCSeyK4EeeU04nzoTW6Sqh77 gTK3T9rPy6QPjD7IrFNZeLwwDfy5SFe9G2vzbJ1geyMgSdBAMITOXK9cdAnsCC40 dNfPKly3BCf2SI+6Z3zJXghJZfKa2iucGrpW1Jwnxdwbtf7gzYBwmdu7lCz7o93F pc3Wd7vCCsjl+PafasuGBPPRhqwuo4fbNuTM6D0oaXWd6Y9HoQ6BanortLotoCXO WPCJxqyAU52V1H4lgxP8bgYPZFGRrrabgbqsvDivohSxj4xd822LleF7VZD9Gtos UQIDAQAB -----END PUBLIC KEY-----`; constructor() {} encryptWithPublicKey(valueToEncrypt: string): string { const scheme={ name: 'RSA-OAEP', hash:'sha256' }; const rsa = Forge.pki.publicKeyFromPem(this.publicKey); const encryptedBytes = rsa.encrypt(valueToEncrypt.toString(),'RSA-OAEP'); return window.btoa(encryptedBytes); } }
ASP.NET Core 6端解密中间件代码
using Microsoft.AspNetCore.Cors; using System.Security.Cryptography; using System.Text; namespace DotNetServer.Middleware { [EnableCors("_myAllowSpecificOrigins")] public class Middleware { private readonly RequestDelegate _next; static string privateKey = @"-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEArHQ09caWERhxf9deHJr2AXwBUQuUdmjuZRRTAvkx+VkytEdy cTgt8wNR53jjCCSeyK4EeeU04nzoTW6Sqh77gTK3T9rPy6QPjD7IrFNZeLwwDfy5 SFe9G2vzbJ1geyMgSdBAMITOXK9cdAnsCC40dNfPKly3BCf2SI+6Z3zJXghJZfKa 2iucGrpW1Jwnxdwbtf7gzYBwmdu7lCz7o93Fpc3Wd7vCCsjl+PafasuGBPPRhqwu o4fbNuTM6D0oaXWd6Y9HoQ6BanortLotoCXOWPCJxqyAU52V1H4lgxP8bgYPZFGR rrabgbqsvDivohSxj4xd822LleF7VZD9GtosUQIDAQABAoIBAFnrjeHJVl47nJLI PW407qj/e8BChXroY8WYv2ABh6k4dVPDHU0jufHIfWBwjBCm55RECFl2xgiCkK4v RZIm7YUEaMjekxLfzKuX4RLZswFdPsFMUWADP7uYoii0NqZ+Pku+pnmmBeQWG+L1 eXkafoeeL4srJNKp86UKLGvhiS3Zz9QgvJKw2nYoe901Jh+nngzhO9MaTGWLgJa0 4aTMQCZ8qdA1gG6gQ9W9UnVEY7m8CzkSyXFXz/JlvZ/WY8Wl7PM9+2ovl4np5S4Z MaPBJvVm0/W22MsNDMo6fo8/yiGLu72QyY4X8zQVPp5rtPA1tYr9UcEnhi16AHvz DDUaoHECgYEA6sP2fzqYWisJz+d+deZXmcT2CUCscJJAeXmyH+DZreEJFmF2D+SH Vx1+dcPSDFjfKgmL3u9l0A4gw4jVz3J64QulZtL/DhNKCj6/NFAjfd2lKx1pcHW3 ZOkiMES1FxWPcj7SVkG/PDSetDRQu3mLUwWytch2fwCEGaSLJ6Q45ucCgYEAvA1o q29KCrdcfLH0lh5X58MxHHCGNkT6S2gFY44r8MrQy2Cu3zepQIp+EIVzfVeUALgk 7+5gqbkZf+gUKihSIRg0n6CjplTesJQrGfA/IAmPUpSvKSTYUWhxYLgD6JoTNPHc jZIsQKz3objDZmO6zNaaEDiuDo3AhkufBOYFxAcCgYEApAyz30wu0jNo8+MsN27y n/1GgEi1NyS78SbdFfGlqx+pnf4U5h4nhPSTPe/Mg9xGdbWeC/b2CmEU/A5Oelvh Cgl9V1Dx8gAAqRAXxJKLepS7qlkvKOrZcKaIwXoBoVPrnUXQ7X2cCJIspHg6Qgc5 GJbOvsCKLU1LAjA9HUJgkNkCgYEAjunp2A+Vx5seMK3VYZjh2YKf+isR9IBrb484 OTa88hxQnZ92hrF4cVJPCCNDZ8h89Cb9+1HAKHxBgtFPMdK+x+Prajzc4fWx36Rb NTU95A0f3PSeQbh8pTGoqIZwgf9GBYChyv2BoA1TjJYr+c5lEnMtVpKcxPa5j9Y8 na5qR1UCgYEAiA4bqKD7cJy2GfNokZhxjej8Y9QGf8fKL4rhh3aIl4diQgUfi+1F 12McPmlwsvfnsuIdGkt/eDdp0Phr/smYbEmKniYQBcHmLc97OH99TyNzySMVeZ5R rWP1WXLkWOeDOzpuZwKrUuXTDvHJfCsEqmlEujUWeGXxOVN/aOFZI2s= -----END RSA PRIVATE KEY-----"; public Middleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { if (httpContext.Request.Method == "POST") { try { HttpRequest request = httpContext.Request; using (StreamReader reader = new StreamReader(request.Body)) { string cypherText = await reader.ReadToEndAsync(); byte[] bytesCypherText = Convert.FromBase64String(cypherText); RSA rsa = RSA.Create(); rsa.ImportFromPem(privateKey); byte[] decryptedBytes = rsa.Decrypt(bytesCypherText,RSAEncryptionPadding.OaepSHA256); string decryptedText = Encoding.UTF8.GetString(decryptedBytes) ; Console.WriteLine(decryptedText); httpContext.Request.Body = new MemoryStream(decryptedBytes); httpContext.Request.ContentLength = decryptedBytes.Length; } await _next(httpContext); } catch (Exception e ) { e.ToString(); throw; } } else { await _next(httpContext); } } } }
问题原因及修复方案
核心原因
[object object]是因为加密时直接对对象调用toString()方法,JavaScript中对象默认toString()返回值就是[object object],而非对象的实际内容。
修复步骤
Angular端修正加密逻辑
- 先将加密对象序列化为JSON字符串,再传入加密方法
- 使用node-forge自带的Base64编码工具,避免
window.btoa的编码兼容性问题 - 显式指定OAEP的哈希算法为SHA256,和后端保持一致
修改后的加密方法:
encryptWithPublicKey(valueToEncrypt: any): string { // 将对象转为JSON字符串 const jsonContent = JSON.stringify(valueToEncrypt); const rsa = Forge.pki.publicKeyFromPem(this.publicKey); // 显式指定SHA256哈希算法 const encrypted = rsa.encrypt(jsonContent, 'RSA-OAEP', { md: Forge.md.sha256.create() }); // 使用forge自带的Base64编码 return Forge.util.encode64(encrypted); }ASP.NET Core端验证
解密后的字符串是JSON格式,可直接反序列化为对象使用,当前后端的解密逻辑无需修改,只需确保前端传入的加密内容是正确的JSON字符串加密结果。
额外注意事项
- 公私钥对已匹配,无需更换
- RSA-OAEP加密内容长度有限制(2048位密钥最多加密214字节),若加密大对象,建议先用AES加密对象,再用RSA加密AES密钥
- 两端统一使用UTF-8编码,当前代码已符合要求
内容的提问来源于stack exchange,提问作者Aneeq Rehman
相关产品推荐
相关产品推荐

