前后端RSA加密梳理

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#需要的公钥和私钥不是通用生成的格式,所以需要转换得到

/// 
        /// 使用RSA实现解密
        /// 
        /// 解密数据
        /// 
        public static string RsaDecrypt(string data)
        {
            string privateKey = "2+cnGtvq+9SIFRkOMsJzVuPAfyD29eHKAHpqYA0CQObDepzg/Th87DZdYLbuMf0AcC/mPXQL5l7EIZ7NeWDM7y6IDHora27GlT6c0umVVXg1X/HfGdfRkgl6TOTr4t89eWM5Np5FWhyk1oKmQ93jiDmxQ4jZb1TW4kW8+ocinkU=AQAB

7arj8uW6fJChvW6OrSHldXEsg2qIG0Uo92PrVvaJ8aDign979MMVkREgpTncUNg9LFX8YgVcN/uMMZqvfmcQ8w==

7N15HGqnORSKDb8bVCRnYnINzCzu0Nz9m/GGzFTuD2tS6SqxCiG81QMCPiEgoo/+X5EvN7F6TuAi8iiV6gEh5w==Tfj70gu2c/mLZrenzXtKaY5YuUCxKKk2+HrqkdxOg1xyE7g5daKvJ6nD2REzi751y17mb04s5Bz98KQ8IS81Kw==Xew4MPdtlam6UFcePBAvWo8FP5f1nqZyfdqY6/8lYsHY35JJH05fdUu7IO275hoY8MY+JeRfLlWcJc/IGkEWsw==vzlq1Fc7ki8jqyzo3zFdKHDynwZBHZ1QtYN4f6+r2MPCiv4GIT6dLJzbXf7fOW17ieicH3QISG2knWvmRdpXJg==SbwlYZ0yGsT16FUhbKXE9PKjPj14cZQHHsftWU2jXs3B6CAoVOAXC0FjaCWOkxZpijSVeC+sOc+25isQbM2niUCsME6dKZJ5AJnjQQ08SwEu6k2Sxa9Pf7H6w5s/RfZBALBGtwxI2ti9hm04WYwQUfLIG+RkbmZK/6c5yqCGE7U=
"
; //创建RSA对象并载入[私钥] RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider(); rsaPrivate.FromXmlString(privateKey); string[] arr = data.Split('^'); string ret = ""; foreach (var o in arr) { if (o != "") { //对数据进行解密 //使用Base64将string转换为byte byte[] privateValue = rsaPrivate.Decrypt(Convert.FromBase64String(o), false); string privateStr = Encoding.UTF8.GetString(privateValue); ret += privateStr; } } return ret; } /// /// 使用RSA实现加密 /// /// 加密数据 /// public static string RsaEncrypt(string data) { string publicKey = "w9xnuqU0kh+AvhqyNUo6RGarxl+INuTe0X9OWp8q5Y0qQHvcmYCFXLoPPVsz3CJy1LfFZTBd65ocm6mWrPSxc1HJEdzY5AOuD5CHXPu10vpEFErxMBAbE4LQbj94kUIeb7YdMA1TTB7zCYWiVaP5lp3SIahRztZlejaAwQ3JUhk=AQAB"; 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#需要格式的逻辑如下:

       /// 
        /// 把通用的RSA私钥转换成C#需要的
        /// 
        /// 
        /// 
        public static string RSAPrivateKey2DotNet(string privateKey)
        {
            var data = Convert.FromBase64String(privateKey);
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
            return string.Format("{0}{1}

{2}

{3}{4}{5}{6}{7}
"
,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())); } /// /// 把通用的RSA公钥转换为C#需要的 /// /// /// public static string RSAPublicKey2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("{0}{1}",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#补全加密串方法

/// 
/// 补全密文
/// 
/// 密文
/// 秘钥长度
/// 补全后的密文
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
{
    /// 
    /// 可以通过http://web.chacuo.net/netrsakeypair/在线生成rsa秘钥对
    /// 
    /// 
    /// 
    /// 
    /*
    -----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="));
        }

        /// 
        /// 补全密文
        /// 
        /// 密文
        /// 秘钥长度
        /// 补全后的密文
        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实现解密
        /// 
        /// 解密数据
        /// 
        public static string RsaDecrypt(string data)
        {
            string privateKey = "1ooE0EBfhxKwbk01nMxnEI9JW+4k6nHXKNqlFcbzfVUNwn+VmFJ/vUihJTLOSQG+38q0YlW2UEyg1SOWjb/ORzHpJq2197UZU3rs5ZMsyc2MyQPqojZ0HN/Q64YcQLt0I50IGp5UcguNKeS/bLbL3IyndtIJkqQhD3t2NA1zhJk=AQAB

/lQJmrlmztI9hZejIJOyWpCKhc7D23w4g19gLEC0+H5NsxyaNtrooEP/wp6bUijblO8ZEyVHewS56sBdkLoBJQ==

1/MHBe5zZ7GOoJhezCKOJISUBmWyWt1jUPA+l9XqoJSGeer4oyNLIqkjSPVqueDO4kq3DldLuON2HkodCNp9ZQ==IRspYOWvd06wyXoStwPi3J0iGwbuQdzqslcw+rG1nP87+AvKG0flri8L1Pa2ezxsUPfKyM46fs3/sYo248cCrQ==aypswtHJrZzcxe+3o6BGX/L3LpGLSDJzlfgTZ/A9poDul1Q3HWZnZAUBwLQhyaq5oG0pmNFTf6ZJuNBYxkr/TQ==XUrOs7JuMKPbPAA9diRgJG8aQoguxDw69+8RCjF3ySoHkzUeFtfqB8pTUew0Gq55FVlvRgmagpxG2aFvDB89vw==YgbUZjdTrssqVGvw+EEpQpbGBTxOH9V+Y0tsLQQn03eefuV+/AeOGHXsM6wAN7mVdnoPa/MQB6bLwjetnf0rCePxrrOuZGmndxuP51DzTo/M+9YRJg+yDI6uON1aZyLnZb2ecGqUoYbbn+VxAEs7yliiLozzD/A9/FMyx50bJZE=
"
; //创建RSA对象并载入[私钥] RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider(); rsaPrivate.FromXmlString(privateKey); string[] arr = data.Split('^'); string ret = ""; foreach (var o in arr) { if (o != "") { //对数据进行解密 //使用Base64将string转换为byte byte[] privateValue = rsaPrivate.Decrypt(Convert.FromBase64String(o), false); string privateStr = Encoding.UTF8.GetString(privateValue); ret += privateStr; } } return ret; } /// /// 把通用的RSA私钥转换成C#需要的 /// /// /// public static string RSAPrivateKey2DotNet(string privateKey) { var data = Convert.FromBase64String(privateKey); RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); return string.Format("{0}{1}

{2}

{3}{4}{5}{6}{7}
"
,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())); } /// /// 把通用的RSA公钥转换为C#需要的 /// /// /// public static string RSAPublicKey2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("{0}{1}",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); } } }

你可能感兴趣的:(C#,c#,前端,javascript)