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

RSA加密特殊字符解密异常求助(Angular+.NET)

RSA加密含特殊字符(如é)后解密乱码处理方案

问题场景

前端Angular使用Forge库通过RSA公钥加密包含特殊字符(如é)的文本,后端.NET用私钥解密时出现乱码,例如原文本"demoé"解密后变为"demo�"。

前端加密代码(原版本)

publicKey: string = `-----BEGIN PUBLIC KEY-----  
  // 公钥内容
  -----END PUBLIC KEY-----`;
let encryptedCredential = {};
const rsa = Forge.pki.publicKeyFromPem(this.publicKey);
Object.keys(empDetails).forEach(keyElement =>{
  encryptedCredential[keyElement] = Forge.util.encode64(rsa.encrypt(empDetails[keyElement].toString()));
});

后端解密代码(原版本)

RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
using (TextReader privateKeyStringReader = new StringReader(File.ReadAllText(System.Web.HttpContext.Current.Request.MapPath("~\\RSA\\rsakey.pem"))))
{
    AsymmetricCipherKeyPair pemReader = (AsymmetricCipherKeyPair)new PemReader(privateKeyStringReader).ReadObject();
    RSAParameters rsaPrivateCrtKeyParameters = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)pemReader.Private);
    
    rsaCryptoServiceProvider.ImportParameters(rsaPrivateCrtKeyParameters);
}
var decryptedBytes = rsaCryptoServiceProvider.Decrypt(Convert.FromBase64String(cipherText), false);
return Encoding.UTF8.GetString(decryptedBytes, 0, decryptedBytes.Length);

问题原因

核心是字符编码不一致:

  • Forge的rsa.encrypt()方法直接传入字符串时,默认使用**ISO-8859-1(Latin-1)**编码将字符串转换为字节,而é在ISO-8859-1中是单字节0xE9;
  • 后端解密后用UTF-8解码,0xE9不是有效的UTF-8字节(UTF-8中é是双字节0xC3 0xA9),因此被解析为无效字符�。

解决方案

1. 修改前端加密逻辑:明确使用UTF-8编码

在加密前,将字符串转换为UTF-8编码的字节数组,再传入加密方法。Forge提供了Forge.util.encodeUtf8工具实现这一点:

publicKey: string = `-----BEGIN PUBLIC KEY-----  
  // 公钥内容
  -----END PUBLIC KEY-----`;
let encryptedCredential = {};
const rsa = Forge.pki.publicKeyFromPem(this.publicKey);
Object.keys(empDetails).forEach(keyElement =>{
  // 将字符串转为UTF-8字节后再加密
  const utf8Bytes = Forge.util.encodeUtf8(empDetails[keyElement].toString());
  encryptedCredential[keyElement] = Forge.util.encode64(rsa.encrypt(utf8Bytes));
});

2. 后端代码无需修改

后端原本使用Encoding.UTF8.GetString()解码,现在前端加密时已用UTF-8编码,解密后能正确解析特殊字符。

验证

加密"demoé"时,前端会将其转为UTF-8字节0x64 0x65 0x6D 0x6F 0xC3 0xA9,加密后传递到后端,解密得到相同的字节数组,用UTF-8解码即可还原为"demoé"。

内容的提问来源于stack exchange,提问作者chaitanya reddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:46:01