C#RSA解密报System.FormatException:“The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.”

最近改进登录加密验证部分碰到个奇怪的问题。就是前台js通过RSA加密的数据提交到后台C#后,少概率界面会报上面异常。开始给测试时候还没觉得是个事,随着不停偶发出现,就觉得这应该是一个bug。为此花了半天查找这个问题。

这里先说说为什么要用RSA加密解密。因为网站的代码和js对用户是可见的,如果采用对称加密的话那么用户可以通过看js就知道怎么解密数据了。所以为了保证传输重要数据的安全性,需要非对称加密。js给后台提交的数据用服务端给js提供的公钥加密数据。提交到后台用自己私钥解密数据。服务器给js端返回的数据用js给服务器提供的公钥加密,js用自己持有的私钥解密。这样用户在网页端只能看到一个秘钥。就能保证传输的安全性。

完整示例

可以从http://web.chacuo.net/netrsakeypair/在线生成公私钥对,需要两对。一对给前端往后台提交数据加密用。一对给后台返回数据给前端用

JS端的加密解密实现

//用RSA加密数据串,后台用LIS.Core.Util.RsaUtil.RsaDecrypt解密
function RsaEncrypt(str) {if (str == null || str == "") {return "";}//公钥var PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDb5yca2+r71IgVGQ4ywnNW48B/
IPb14coAempgDQJA5sN6nOD9OHzsNl1gtu4x/QBwL+Y9dAvmXsQhns15YMzvLogM
eitrbsaVPpzS6ZVVeDVf8d8Z19GSCXpM5Ovi3z15Yzk2nkVaHKTWgqZD3eOIObFD
iNlvVNbiRbz6hyKeRQIDAQAB';//使用公钥加密var encrypt = new JSEncrypt();encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');var num = 50;var encrypted = "";for (var i = 0; i < str.length; i += num) {var startIndex = i;var endIndex = i + num;if (endIndex > str.length) {endIndex = str.length;}var one = str.substring(startIndex, endIndex);if (one != "") {var oneencrypted = encrypt.encrypt(one);//补全加密数据位数,其他语言没自动补全oneencrypted = btoa(atob(oneencrypted).padStart(128, "\0"));if (encrypted == "") {encrypted += oneencrypted;}else {encrypted += "^" + oneencrypted;}}}return encrypted;
}//用RSA解密数据串,后台用LIS.Core.Util.RsaUtil.RsaEncrypt加密
function RsaDecrypt(str) {if (str == null || str == "") {return "";}//私钥钥var Private_KEY = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMPcZ7qlNJIfgL4a
sjVKOkRmq8ZfiDbk3tF/TlqfKuWNKkB73JmAhVy6Dz1bM9wictS3xWUwXeuaHJup
lqz0sXNRyRHc2OQDrg+Qh1z7tdL6RBRK8TAQGxOC0G4/eJFCHm+2HTANU0we8wmF
olWj+Zad0iGoUc7WZXo2gMENyVIZAgMBAAECgYEAkJMJHoUEITiP18Ps99kq2YLQ
GUY7TgnzT8EhHVOQXpGtNpw3Yje0OZY92ZSQ21WyXcKpOuBQ87B2nZC5YEHfGWuY
+EJlS0ax4ckj7aEUfI1PmcblwOyAZDtYXNOigaJDLyoOYgsE3xLevdDgK94+dPp7
vt5f6MC7hydL0083L4ECQQD9N67yjkQGorxl0B9bkQPUJJjWf96nwCLLizw8LbvN
VYrbvhCF86Pag4bCphIBHUn0dUjcDljVg6hxELRirNDlAkEAxgNfzpMzFOTW+3CM
Nxlu/xxFBRqd5SboGiQA970Gn9BhNKSSweLtXAcb47iWc6/feXpY5HxST8Wf+GSw
na2NJQJBAOFx6zwfd+dkilIne1O+B+ef8cfALw+xnAkW3TlDCprlV20PioyIgFDz
m07AJvWBCzAwH/90cpke0CBiXAgijxUCQCtvggymbYYfzKjLP3a2tYpwgRNli01B
A5j4XN37MQDNjQUnNKojRT3ysUN6skYeRj83f1hfjQ7Coxyxuaxc7aECQHj3Hz2w
rKEUpNoxW3TwxHHvO7uHyD0BbAU+fdmEjrfQdkgfKLzX6kSpWpohkgkncY1WqUTV
GhQweu2nxnaLM+g=';//使用公钥加密var decrypt = new JSEncrypt();decrypt.setPrivateKey('-----BEGIN PRIVATE KEY-----' + Private_KEY + '-----END PRIVATE KEY-----');var arr = str.split("^");var decryptMsg = "";for (var i = 0; i < arr.length; i++) {if (arr[i] != "") {var onedecryptMsg = decrypt.decrypt(arr[i]);decryptMsg += onedecryptMsg;}}return decryptMsg;
}

C#端的加密解密实现,由于C#需要的公钥和私钥不是通用生成的格式,所以需要转换得到

/// <summary>/// 使用RSA实现解密/// </summary>/// <param name="data">解密数据</param>/// <returns></returns>public static string RsaDecrypt(string data){string privateKey = "<RSAKeyValue><Modulus>2+cnGtvq+9SIFRkOMsJzVuPAfyD29eHKAHpqYA0CQObDepzg/Th87DZdYLbuMf0AcC/mPXQL5l7EIZ7NeWDM7y6IDHora27GlT6c0umVVXg1X/HfGdfRkgl6TOTr4t89eWM5Np5FWhyk1oKmQ93jiDmxQ4jZb1TW4kW8+ocinkU=</Modulus><Exponent>AQAB</Exponent><P>7arj8uW6fJChvW6OrSHldXEsg2qIG0Uo92PrVvaJ8aDign979MMVkREgpTncUNg9LFX8YgVcN/uMMZqvfmcQ8w==</P><Q>7N15HGqnORSKDb8bVCRnYnINzCzu0Nz9m/GGzFTuD2tS6SqxCiG81QMCPiEgoo/+X5EvN7F6TuAi8iiV6gEh5w==</Q><DP>Tfj70gu2c/mLZrenzXtKaY5YuUCxKKk2+HrqkdxOg1xyE7g5daKvJ6nD2REzi751y17mb04s5Bz98KQ8IS81Kw==</DP><DQ>Xew4MPdtlam6UFcePBAvWo8FP5f1nqZyfdqY6/8lYsHY35JJH05fdUu7IO275hoY8MY+JeRfLlWcJc/IGkEWsw==</DQ><InverseQ>vzlq1Fc7ki8jqyzo3zFdKHDynwZBHZ1QtYN4f6+r2MPCiv4GIT6dLJzbXf7fOW17ieicH3QISG2knWvmRdpXJg==</InverseQ><D>SbwlYZ0yGsT16FUhbKXE9PKjPj14cZQHHsftWU2jXs3B6CAoVOAXC0FjaCWOkxZpijSVeC+sOc+25isQbM2niUCsME6dKZJ5AJnjQQ08SwEu6k2Sxa9Pf7H6w5s/RfZBALBGtwxI2ti9hm04WYwQUfLIG+RkbmZK/6c5yqCGE7U=</D></RSAKeyValue>";//创建RSA对象并载入[私钥]RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider();rsaPrivate.FromXmlString(privateKey);string[] arr = data.Split('^');string ret = "";foreach (var o in arr){if (o != ""){//对数据进行解密//使用Base64将string转换为bytebyte[] privateValue = rsaPrivate.Decrypt(Convert.FromBase64String(o), false);string privateStr = Encoding.UTF8.GetString(privateValue);ret += privateStr;}}return ret;}/// <summary>/// 使用RSA实现加密/// </summary>/// <param name="data">加密数据</param>/// <returns></returns>public static string RsaEncrypt(string data){string publicKey = "<RSAKeyValue><Modulus>w9xnuqU0kh+AvhqyNUo6RGarxl+INuTe0X9OWp8q5Y0qQHvcmYCFXLoPPVsz3CJy1LfFZTBd65ocm6mWrPSxc1HJEdzY5AOuD5CHXPu10vpEFErxMBAbE4LQbj94kUIeb7YdMA1TTB7zCYWiVaP5lp3SIahRztZlejaAwQ3JUhk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();rsa.FromXmlString(publicKey);int num = 50;string encrypted = "";for (var i = 0; i < data.Length; i += num){var startIndex = i;var endIndex = i + num;if (endIndex > data.Length - 1){endIndex = data.Length;}string  one = data.Substring(startIndex, endIndex-startIndex);if (one != ""){string oneencrypted = Convert.ToBase64String(rsa.Encrypt(Encoding.UTF8.GetBytes(one), false));if (encrypted == ""){encrypted += oneencrypted;}else{encrypted += "^" + oneencrypted;}}}return encrypted;}

把通用公钥和私钥格式转换为C#需要格式的逻辑如下:

       /// <summary>/// 把通用的RSA私钥转换成C#需要的/// </summary>/// <param name="privateKey"></param>/// <returns></returns>public static string RSAPrivateKey2DotNet(string privateKey){var data = Convert.FromBase64String(privateKey);RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// 把通用的RSA公钥转换为C#需要的/// </summary>/// <param name="publicKey"></param>/// <returns></returns>public static string RSAPublicKey2DotNet(string publicKey){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}

1.最先怀疑是不是js提交到后台串被截断了或者转义了,通过在前端和后台写日志发现提交的串没变。
2.然后怀疑是不是我写的加密切割有问题,因为RSA加密结果长度不得大于秘钥长度,所以我50一切割了,我把切割调整后发现也是不行。
3.然后我就用js循环1万次往C#提交解密,发现失败概率确实不低,基本几百次就有失败的,因此把怀疑点放到是不是失败时候串不完整了。为此查了很久资料,资料说RSA加密串按理应该等于秘钥长度。正常语言解密就是按这个约定实现的。但是jsencrypt.js的加密逻辑如果加密串长度不够秘钥串长度没有自动做补全,但是他自己的解密算法尝试做了补全。所以他自己加密的串解密不会报错,但是C#这些没自动补全的语言就报错。所以解决方式有两个:

1.jsencrypt.js加密后补全加密串。
2.其他语言解密方法尝试补全加密串后再解密。

JS修改部分:

//加密数据
var oneencrypted = encrypt.encrypt(one);
//补全加密数据位数,其他语言没自动补全
oneencrypted = btoa(atob(oneencrypted).padStart(128, "\0"));

C#补全加密串方法

/// <summary>
/// 补全密文
/// </summary>
/// <param name="strCiphertext">密文</param>
/// <param name="keySize">秘钥长度</param>
/// <returns>补全后的密文</returns>
private static string CorrectionCiphertext(string strCiphertext, int keySize = 1024)
{int ciphertextLength = keySize / 8;byte[] data = Convert.FromBase64String(strCiphertext);var newData = new List<byte>(data);while (newData.Count < ciphertextLength){newData.Insert(0, 0x00);}return Convert.ToBase64String(newData.ToArray());
}

以上就是碰到的jsencrypt.js加密后台解密的坑,顺带把通用RSA秘钥转换为C#需要的秘钥一起梳理一下分享给小伙伴。

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;namespace ConsoleApp2
{/// <summary>/// 可以通过http://web.chacuo.net/netrsakeypair/在线生成rsa秘钥对/// /// /// /// </summary>/*-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDb5yca2+r71IgVGQ4ywnNW48B/
IPb14coAempgDQJA5sN6nOD9OHzsNl1gtu4x/QBwL+Y9dAvmXsQhns15YMzvLogM
eitrbsaVPpzS6ZVVeDVf8d8Z19GSCXpM5Ovi3z15Yzk2nkVaHKTWgqZD3eOIObFD
iNlvVNbiRbz6hyKeRQIDAQAB
-----END PUBLIC KEY----------BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANvnJxrb6vvUiBUZ
DjLCc1bjwH8g9vXhygB6amANAkDmw3qc4P04fOw2XWC27jH9AHAv5j10C+ZexCGe
zXlgzO8uiAx6K2tuxpU+nNLplVV4NV/x3xnX0ZIJekzk6+LfPXljOTaeRVocpNaC
pkPd44g5sUOI2W9U1uJFvPqHIp5FAgMBAAECgYBJvCVhnTIaxPXoVSFspcT08qM+
PXhxlAcex+1ZTaNezcHoIChU4BcLQWNoJY6TFmmKNJV4L6w5z7bmKxBszaeJQKww
Tp0pknkAmeNBDTxLAS7qTZLFr09/sfrDmz9F9kEAsEa3DEja2L2GbThZjBBR8sgb
5GRuZkr/pznKoIYTtQJBAO2q4/LlunyQob1ujq0h5XVxLINqiBtFKPdj61b2ifGg
4oJ/e/TDFZERIKU53FDYPSxV/GIFXDf7jDGar35nEPMCQQDs3Xkcaqc5FIoNvxtU
JGdicg3MLO7Q3P2b8YbMVO4Pa1LpKrEKIbzVAwI+ISCij/5fkS83sXpO4CLyKJXq
ASHnAkBN+PvSC7Zz+Ytmt6fNe0ppjli5QLEoqTb4euqR3E6DXHITuDl1oq8nqcPZ
ETOLvnXLXuZvTizkHP3wpDwhLzUrAkBd7Dgw922VqbpQVx48EC9ajwU/l/WepnJ9
2pjr/yViwdjfkkkfTl91S7sg7bvmGhjwxj4l5F8uVZwlz8gaQRazAkEAvzlq1Fc7
ki8jqyzo3zFdKHDynwZBHZ1QtYN4f6+r2MPCiv4GIT6dLJzbXf7fOW17ieicH3QI
SG2knWvmRdpXJg==
-----END PRIVATE KEY----------BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD3Ge6pTSSH4C+GrI1SjpEZqvG
X4g25N7Rf05anyrljSpAe9yZgIVcug89WzPcInLUt8VlMF3rmhybqZas9LFzUckR
3NjkA64PkIdc+7XS+kQUSvEwEBsTgtBuP3iRQh5vth0wDVNMHvMJhaJVo/mWndIh
qFHO1mV6NoDBDclSGQIDAQAB
-----END PUBLIC KEY----------BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMPcZ7qlNJIfgL4a
sjVKOkRmq8ZfiDbk3tF/TlqfKuWNKkB73JmAhVy6Dz1bM9wictS3xWUwXeuaHJup
lqz0sXNRyRHc2OQDrg+Qh1z7tdL6RBRK8TAQGxOC0G4/eJFCHm+2HTANU0we8wmF
olWj+Zad0iGoUc7WZXo2gMENyVIZAgMBAAECgYEAkJMJHoUEITiP18Ps99kq2YLQ
GUY7TgnzT8EhHVOQXpGtNpw3Yje0OZY92ZSQ21WyXcKpOuBQ87B2nZC5YEHfGWuY
+EJlS0ax4ckj7aEUfI1PmcblwOyAZDtYXNOigaJDLyoOYgsE3xLevdDgK94+dPp7
vt5f6MC7hydL0083L4ECQQD9N67yjkQGorxl0B9bkQPUJJjWf96nwCLLizw8LbvN
VYrbvhCF86Pag4bCphIBHUn0dUjcDljVg6hxELRirNDlAkEAxgNfzpMzFOTW+3CM
Nxlu/xxFBRqd5SboGiQA970Gn9BhNKSSweLtXAcb47iWc6/feXpY5HxST8Wf+GSw
na2NJQJBAOFx6zwfd+dkilIne1O+B+ef8cfALw+xnAkW3TlDCprlV20PioyIgFDz
m07AJvWBCzAwH/90cpke0CBiXAgijxUCQCtvggymbYYfzKjLP3a2tYpwgRNli01B
A5j4XN37MQDNjQUnNKojRT3ysUN6skYeRj83f1hfjQ7Coxyxuaxc7aECQHj3Hz2w
rKEUpNoxW3TwxHHvO7uHyD0BbAU+fdmEjrfQdkgfKLzX6kSpWpohkgkncY1WqUTV
GhQweu2nxnaLM+g=
-----END PRIVATE KEY-----*/class Program{static void Main(string[] args){string pra1 = RSAPrivateKey2DotNet("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANvnJxrb6vvUiBUZDjLCc1bjwH8g9vXhygB6amANAkDmw3qc4P04fOw2XWC27jH9AHAv5j10C+ZexCGezXlgzO8uiAx6K2tuxpU+nNLplVV4NV/x3xnX0ZIJekzk6+LfPXljOTaeRVocpNaCpkPd44g5sUOI2W9U1uJFvPqHIp5FAgMBAAECgYBJvCVhnTIaxPXoVSFspcT08qM+PXhxlAcex+1ZTaNezcHoIChU4BcLQWNoJY6TFmmKNJV4L6w5z7bmKxBszaeJQKwwTp0pknkAmeNBDTxLAS7qTZLFr09/sfrDmz9F9kEAsEa3DEja2L2GbThZjBBR8sgb5GRuZkr/pznKoIYTtQJBAO2q4/LlunyQob1ujq0h5XVxLINqiBtFKPdj61b2ifGg4oJ/e/TDFZERIKU53FDYPSxV/GIFXDf7jDGar35nEPMCQQDs3Xkcaqc5FIoNvxtUJGdicg3MLO7Q3P2b8YbMVO4Pa1LpKrEKIbzVAwI+ISCij/5fkS83sXpO4CLyKJXqASHnAkBN+PvSC7Zz+Ytmt6fNe0ppjli5QLEoqTb4euqR3E6DXHITuDl1oq8nqcPZETOLvnXLXuZvTizkHP3wpDwhLzUrAkBd7Dgw922VqbpQVx48EC9ajwU/l/WepnJ92pjr/yViwdjfkkkfTl91S7sg7bvmGhjwxj4l5F8uVZwlz8gaQRazAkEAvzlq1Fc7ki8jqyzo3zFdKHDynwZBHZ1QtYN4f6+r2MPCiv4GIT6dLJzbXf7fOW17ieicH3QISG2knWvmRdpXJg==");Console.WriteLine("私钥1:"+ pra1);string pra2 = RSAPrivateKey2DotNet("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMPcZ7qlNJIfgL4asjVKOkRmq8ZfiDbk3tF/TlqfKuWNKkB73JmAhVy6Dz1bM9wictS3xWUwXeuaHJuplqz0sXNRyRHc2OQDrg+Qh1z7tdL6RBRK8TAQGxOC0G4/eJFCHm+2HTANU0we8wmFolWj+Zad0iGoUc7WZXo2gMENyVIZAgMBAAECgYEAkJMJHoUEITiP18Ps99kq2YLQGUY7TgnzT8EhHVOQXpGtNpw3Yje0OZY92ZSQ21WyXcKpOuBQ87B2nZC5YEHfGWuY+EJlS0ax4ckj7aEUfI1PmcblwOyAZDtYXNOigaJDLyoOYgsE3xLevdDgK94+dPp7vt5f6MC7hydL0083L4ECQQD9N67yjkQGorxl0B9bkQPUJJjWf96nwCLLizw8LbvNVYrbvhCF86Pag4bCphIBHUn0dUjcDljVg6hxELRirNDlAkEAxgNfzpMzFOTW+3CMNxlu/xxFBRqd5SboGiQA970Gn9BhNKSSweLtXAcb47iWc6/feXpY5HxST8Wf+GSwna2NJQJBAOFx6zwfd+dkilIne1O+B+ef8cfALw+xnAkW3TlDCprlV20PioyIgFDzm07AJvWBCzAwH/90cpke0CBiXAgijxUCQCtvggymbYYfzKjLP3a2tYpwgRNli01BA5j4XN37MQDNjQUnNKojRT3ysUN6skYeRj83f1hfjQ7Coxyxuaxc7aECQHj3Hz2wrKEUpNoxW3TwxHHvO7uHyD0BbAU+fdmEjrfQdkgfKLzX6kSpWpohkgkncY1WqUTVGhQweu2nxnaLM+g=");Console.WriteLine("私钥2:" + pra2);string pub1 = RSAPublicKey2DotNet("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDb5yca2+r71IgVGQ4ywnNW48B/IPb14coAempgDQJA5sN6nOD9OHzsNl1gtu4x/QBwL+Y9dAvmXsQhns15YMzvLogMeitrbsaVPpzS6ZVVeDVf8d8Z19GSCXpM5Ovi3z15Yzk2nkVaHKTWgqZD3eOIObFDiNlvVNbiRbz6hyKeRQIDAQAB");Console.WriteLine("公钥1:" + pub1);string pub2 = RSAPublicKey2DotNet("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD3Ge6pTSSH4C+GrI1SjpEZqvGX4g25N7Rf05anyrljSpAe9yZgIVcug89WzPcInLUt8VlMF3rmhybqZas9LFzUckR3NjkA64PkIdc+7XS+kQUSvEwEBsTgtBuP3iRQh5vth0wDVNMHvMJhaJVo/mWndIhqFHO1mV6NoDBDclSGQIDAQAB");Console.WriteLine("公钥2:" + pub2);//RsaDecrypt(CorrectionCiphertext("VtHQdECGRBOezGyx7LI0Q/BV2bHT2TbUzGmZBB3jxYZfgQCY+W557CxRw/hwemp80Xqg8sufOkvh6ERvwP7Vdout2B8KoFa9QesIos1qEOhPgJzKZQ7cKVDKi6Fa5QO6tXdmZhfKf3dZekGK7wUW/toiFkZDbQPU2Q381CcV3A==^en5GZwC8KPd6ggkDUm4UfBFspZjahym6tPFOw6O5PnLR/feO3ECUKg3sZ4p4HSXv92n1oKQDxQb3iEXR6vWfK2uoW2zFbJFDJdkyP4Ko2dT5MLMt7b86qkqRtpxW0GhL3Am6PInXAz5snKB3piDcqmlGgwcuHMoi0h5fiDGLq6I="));}/// <summary>/// 补全密文/// </summary>/// <param name="strCiphertext">密文</param>/// <param name="keySize">秘钥长度</param>/// <returns>补全后的密文</returns>private static string CorrectionCiphertext(string strCiphertext, int keySize = 1024){int ciphertextLength = keySize / 8;byte[] data = Convert.FromBase64String(strCiphertext);var newData = new List<byte>(data);while (newData.Count < ciphertextLength){newData.Insert(0, 0x00);}return Convert.ToBase64String(newData.ToArray());}/// 使用RSA实现解密/// </summary>/// <param name="data">解密数据</param>/// <returns></returns>public static string RsaDecrypt(string data){string privateKey = "<RSAKeyValue><Modulus>1ooE0EBfhxKwbk01nMxnEI9JW+4k6nHXKNqlFcbzfVUNwn+VmFJ/vUihJTLOSQG+38q0YlW2UEyg1SOWjb/ORzHpJq2197UZU3rs5ZMsyc2MyQPqojZ0HN/Q64YcQLt0I50IGp5UcguNKeS/bLbL3IyndtIJkqQhD3t2NA1zhJk=</Modulus><Exponent>AQAB</Exponent><P>/lQJmrlmztI9hZejIJOyWpCKhc7D23w4g19gLEC0+H5NsxyaNtrooEP/wp6bUijblO8ZEyVHewS56sBdkLoBJQ==</P><Q>1/MHBe5zZ7GOoJhezCKOJISUBmWyWt1jUPA+l9XqoJSGeer4oyNLIqkjSPVqueDO4kq3DldLuON2HkodCNp9ZQ==</Q><DP>IRspYOWvd06wyXoStwPi3J0iGwbuQdzqslcw+rG1nP87+AvKG0flri8L1Pa2ezxsUPfKyM46fs3/sYo248cCrQ==</DP><DQ>aypswtHJrZzcxe+3o6BGX/L3LpGLSDJzlfgTZ/A9poDul1Q3HWZnZAUBwLQhyaq5oG0pmNFTf6ZJuNBYxkr/TQ==</DQ><InverseQ>XUrOs7JuMKPbPAA9diRgJG8aQoguxDw69+8RCjF3ySoHkzUeFtfqB8pTUew0Gq55FVlvRgmagpxG2aFvDB89vw==</InverseQ><D>YgbUZjdTrssqVGvw+EEpQpbGBTxOH9V+Y0tsLQQn03eefuV+/AeOGHXsM6wAN7mVdnoPa/MQB6bLwjetnf0rCePxrrOuZGmndxuP51DzTo/M+9YRJg+yDI6uON1aZyLnZb2ecGqUoYbbn+VxAEs7yliiLozzD/A9/FMyx50bJZE=</D></RSAKeyValue>";//创建RSA对象并载入[私钥]RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider();rsaPrivate.FromXmlString(privateKey);string[] arr = data.Split('^');string ret = "";foreach (var o in arr){if (o != ""){//对数据进行解密//使用Base64将string转换为bytebyte[] privateValue = rsaPrivate.Decrypt(Convert.FromBase64String(o), false);string privateStr = Encoding.UTF8.GetString(privateValue);ret += privateStr;}}return ret;}/// <summary>/// 把通用的RSA私钥转换成C#需要的/// </summary>/// <param name="privateKey"></param>/// <returns></returns>public static string RSAPrivateKey2DotNet(string privateKey){var data = Convert.FromBase64String(privateKey);RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// 把通用的RSA公钥转换为C#需要的/// </summary>/// <param name="publicKey"></param>/// <returns></returns>public static string RSAPublicKey2DotNet(string publicKey){RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}}
}

前后端RSA加密梳理相关推荐

  1. java和Vue前后端RSA对称加密

    java和Vue前后端RSA对称加密 参考:https://blog.csdn.net/qq_25623257/article/details/109775531 一.生成秘钥对(公私钥) 在线生成地 ...

  2. 前后端RSA互相加解密、加签验签、密钥对生成(Java)

    目录 一.序言 二.关于PKCS#1和PKCS#8格式密钥 1.简介 2.区别 二.关于JSEncrypt 三.关于jsrsasign 四.前端RSA加解密.加验签示例 1.相关依赖 2.crypto ...

  3. 前后端传输加密代码-java

    介绍 以下代码均使用RSA加密,适用场景:注册.登录时的密码加密.敏感信息加密等 业务流程: 后端使用RSA算法生成一套密钥 前端使用接口获取后端公钥 后端将公钥传给前端,私钥留在本地服务器 前端使用 ...

  4. 微信小程序前后端通讯加密(web应用都可使用)

    最近在做项目的时候,需要前后端加密通信,尝试了几种方法后都没有效果,最后用DES算法终于解决了这个问题 前端加密,后端解密的代码: 微信小程序的前端代码 //引入两个js文件 let des3 = r ...

  5. 使用国密2(SM2)前后端传输加密

    后端工具类 @Data @AllArgsConstructor static class SM2KeyPair {// 公钥private String publicKey;// 前端公钥privat ...

  6. 学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密

    学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密 技术标签: RSA  AES  RSA AES  混合加密  整合 前言:    为了提高安全性采用了RSA,但 ...

  7. 前后端分离API接口如何加密 —— AES加密方案

    场景还原:页面中需要展示手机号,身份证号,因为是前后端分离,所有接口API地址有可能暴露,这样不怀好意的人可以拿到个人敏感信息 解决方案: 1. 敏感信息加掩码,例如:接口返回130**12这样的手机 ...

  8. angular和JAVA实现aes、rsa加密解密,前后端交互,前端加解密和后端JAVA加解密实现

    今天实现了下AES和RSA加密解密,主要的功能是对前后端交互数据进行加密解密,为什么要用到两个算法呢,首先RSA默认的话加密长度是有限的100多个byte吧大约,并且需要公钥私钥,而AES加密没有限制 ...

  9. aes 加密_结合RSA与AES实现前后端加密通信

    结合RSA与AES实现前后端加密通信 一.思路 使用RSA秘钥生成工具生成一对公钥(A)和私钥(B),前端保留A,后端保留B. 前端发送数据时,先生成一串随机16位字符串作为AES的秘钥(C),然后使 ...

  10. rsa前后端加密流程_不懂前后端分离?这篇就够了

    一 传统的开发模式 前后端分离前我们的开发协作模式一般是这样的: 前端写好静态的HTML页面交付给后端开发.静态页面可以本地开发,也无需考虑业务逻辑只需要实现View即可. 后端使用模板引擎去套模板, ...

最新文章

  1. oracle not available
  2. Flash和JavaScript通信
  3. iOS开发之第三方框架Masonry
  4. 《Haskell函数式编程入门》—— 第1章,第1.5节第一个Haskell程序HelloWorld!
  5. ubuntu15.10下code::blocks设置运行窗口为gnome命令行
  6. Echarts --- 各个省份的坐标
  7. java中解密技术是什么_详解Java 加密解密技术的分类和归纳
  8. URL传Base64 造成报错 Illegal base64 character 20
  9. 编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换)
  10. Git 看这一篇就够了!
  11. linux新建java文件夹删除不了怎么办_Linux无法删除文件夹 Device or resource busy
  12. 国内经典BI系统架构分析
  13. c语言仿宋gb2312字体,【仿宋gb2312字体下载】仿宋gb2312字体官方下载 免费版-七喜软件园...
  14. 如何从Word,Excel和PowerPoint文档中提取图像,文本和嵌入式文件
  15. epub电子书格式转换(E-book Conversion翻译) -- calibre
  16. leetcode No5 最长回文子串
  17. 法语入门学习资料汇总
  18. APE文件学习——文件头(1)
  19. kafka之broker
  20. 是你吗?为超炫的 USB 硬件编写更好的软件

热门文章

  1. Java基础加强重温_06:可变参数、集合工具类Collections类、冒泡排序、Map集合、Map集合遍历、Map案例、LinkedHashMap集合、图书管理系统
  2. zblog首页模板修改php,zblog主题模板文件的修改办法
  3. GIT:cherry-pick挑拣提交
  4. 25个移动APP图表设计欣赏(译)
  5. 使用Blast2GO进行GO注释
  6. 共享网络打印机无法连接计算机,电脑中出现共享打印机连接错误问题的解决方法...
  7. 电脑休眠和睡眠的区别
  8. 木木早教机器人说明书_机器人操作说明VS小孩使用指南
  9. 江苏计算机对口高考分数线,单招好还是高考好|江苏省对口单招 历年分数线是多少?...
  10. 手机浏览器 html编辑器,vue移动端富文本编辑器vue-html5-editor