• 前后端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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    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; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    把通用公钥和私钥格式转换为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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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"));
    
    • 1
    • 2
    • 3
    • 4

    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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    以上就是碰到的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())); } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
  • 相关阅读:
    双赢!企业咨询行业和低代码工具的破局之路
    spring MVC执行流程与源码解析
    全场景AI推理引擎MindSpore Lite, 助力HMS Core视频编辑服务打造更智能的剪辑体验
    PyTorch 2.0发布了,一行代码提速76%
    【FFmpeg】视频与图片互相转换 ( 视频与 JPG 静态图片互相转换 | 视频与 GIF 动态图片互相转换 )
    有来实验室|第一篇:Seata1.5.2版本部署和开源全栈商城订单支付业务实战
    JAVA:实现Excel和PDF上下标
    Salesforce中国区解散,谁是替代的最佳选择?
    [HTML]HTML5新增标签
    Netty模型
  • 原文地址:https://blog.csdn.net/zhanglianzhu_91/article/details/126910987