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
相关产品推荐
相关产品推荐

