C# RSA2048 公钥加密,私钥解密

最近开发车辆控制这块,与车上的控制设备进行通信,其中设备向平台注册使用了RSA2048的解密,在网上找了一些加密解密的都是加载XML文件的,公钥(原始的byte[] 294个长度),私钥,我看C#提供的类库里面有一个加载指数,模数的进行解密的功能所以试着实现了一下,下面上代码:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp2
{
    class Program
    { 
        static void Main(string[] args)
        {
            while (true)
            {
                var input = Console.ReadLine();
                #region MyRegion

                #endregion
                ///公钥
                string sql = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwNqreCMpgET1BEA/kPZA
                            eaj+xfG2UWTHOkTyV+28AC0BYxQDfKq7HV1RDaLHR5GBIKC1OK+m5thEBVJg27O8
                            uUp95O88McR17mFw9UVQ5w3Zn9ChK93GzmB1ltob3Sm847YW18KyoxDbqbh6MlRy
                            6yt5v/MDpbbs5lEcwME9YmgGVvayfWDMquFqHnX05pEoE05uvAyDj1UtT7ZlMn6T
                            mOzTLpfoGnkADoyB3LraAa6qGkNWa9/fmV3xU11LH141fidO9iG5L5Gx5xw/JEIx
                            TAblXbxqxsWeCBbkNpW4TqtbX5CH1EdhWYxOL060Ujkr1Qe5Zp0TntaKK2lY4Rsw
                            KQIDAQAB";
                var rsaa = ConvertFromPemPublicKey(sql);
                RSACryptoServiceProvider rsab = new RSACryptoServiceProvider();
                rsab.ImportParameters(rsaa);

                byte[] sample = rsab.Encrypt(Encoding.Default.GetBytes(input), false);
                string info = Convert.ToBase64String(sample);
                Console.WriteLine("加密后:" + info);


                #region 解密


                //秘钥
                byte[] aa = Convert.FromBase64String(info);
                sql = @"MIIEowIBAAKCAQEAwNqreCMpgET1BEA/kPZAeaj+xfG2UWTHOkTyV+28AC0BYxQDfKq7HV1RDaLHR5GBIKC1OK+m5thEBVJg27O8uUp95O88McR17mFw9UVQ5w3Zn9ChK93GzmB1ltob3Sm847YW18KyoxDbqbh6MlRy6yt5v/MDpbbs5lEcwME9YmgGVvayfWDMquFqHnX05pEoE05uvAyDj1UtT7ZlMn6TmOzTLpfoGnkADoyB3LraAa6qGkNWa9/fmV3xU11LH141fidO9iG5L5Gx5xw/JEIxTAblXbxqxsWeCBbkNpW4TqtbX5CH1EdhWYxOL060Ujkr1Qe5Zp0TntaKK2lY4RswKQIDAQABAoIBAH2p/zE5OEGsrTsn4kPDMiAUTm8NIY/H60m8w20oK+ixasX0tJD3bxWjSL1p5BBub4WjMnLNgiPJqAkPtK10YPUb5QzYFpEXQwEh3Uj08dKc48GPYHYE/RZdJEI3vRBPshVvAVN2OpCm23usCXPiMz+qBJte7nF80MEC+YlgYW9M1xDYseAHCfpbF38KIUrI235YN5G72MhFBQc8SrJpOp4qvHWR2yQ25ryUeqOMqqfJchMbP3r49mxU+wXUNicuRfEvFVbvwGG5NiurizD4Ts/+lR5EFJUUaF9qJzKl9BifiwVS6Cgwi9Pl4Em9Y4YUok9Wncw7xC3WTZX8sbqdUQECgYEA7iLieUJl8ngHd8tGjmHdTmlZBJftiSsKcS0S6iMbcVlR/oBT09sV3aJFGcVQZGCOwlTNCUUUJ0nc8r/aR0daODBYQLuEkY2pBZ5K1OqPZ6H8CRsyEl1E0CLA4CGRH8l3Ua/otFdxgnSuTzla5TK4uCTyO0NwXyj/vFL6CMsGFBUCgYEAz1IytWOw11ATSxUeIjJYgCGLMzeq20pP1avi9y7ri1QAudKIRWqJh/oq4FJ01EWYmsV6aQadAB61zNOvKRY9E6fYCFeMziJIciFKUvBNNsRWy5bkM58Q+z3BZv2hqncU8G5ZYcK0wWvPlVwFYMx8RveVdkFUsw9Wfu3DMXH5zMUCgYBY6/3Vec3HtLpVKTq3gCO7W+s5o+G3DrNff41IkMN2l/veJN0ohu6rTCSxctSKJuQn/LJze7AC27n9i1Zet24g/Sx3P45JK7SpvGoFB3F1KS+L1vPjl6BSeCe9ics/K2O6xQ0ICn8AT8GnI6ulWkNPv7wUFSKo5g5YrENhdS5X4QKBgFzprrYiLm/ggDUHCtEylP0fi13x1c2feTX+aaJz0bZIeGbPFqldfLOHB04vRhKX+jNqy1hkUVpraPiZ6gdU4xx6/VOHwR/kt2kGyGNxNHmV9nwZbL5BzH98hr+cbaaS5bx3B/HLK+z/XzHF4tcl7ZB0hvRPhSEWf6I09mSjetstAoGBAL169VzKB3jdchzGUSHqoo21kpad1zSKWzVYyu9gmtFg4O51RHCKbo7k6/dt30UnSUQ75icUlJfO0ZdKPqUnJHUUEGfkuMihXRPtf0h9mEiUSO3CLNbMsr4qzcIcfpfAlYCw/e0eLrY98LTDC152KXeFzNJHFwRiDYcIoV5GjGSR";
                var b = DecodeRSAPrivateKey(sql);
                byte[] vs = b.Decrypt(aa, false);
                string str = System.Text.Encoding.Default.GetString(vs);
                Console.WriteLine("解密后:" + str);
                #endregion

            }
        }

        public static RSACryptoServiceProvider DecodeRSAPrivateKey(string priKey)
        {
            var privkey = Convert.FromBase64String(priKey);
            byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

            // ---------  Set up stream to decode the asn.1 encoded RSA private key  ------
            MemoryStream mem = new MemoryStream(privkey);
            BinaryReader binr = new BinaryReader(mem);    //wrap Memory Stream with BinaryReader for easy reading
            byte bt = 0;
            ushort twobytes = 0;
            int elems = 0;
            try
            {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                    binr.ReadByte();        //advance 1 byte
                else if (twobytes == 0x8230)
                    binr.ReadInt16();       //advance 2 bytes
                else
                    return null;

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102) //version number
                    return null;
                bt = binr.ReadByte();
                if (bt != 0x00)
                    return null;


                //------  all private key components are Integer sequences ----
                elems = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                D = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                P = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                Q = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DP = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DQ = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                IQ = binr.ReadBytes(elems);

                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                RSAParameters RSAparams = new RSAParameters();
                RSAparams.Modulus = MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D = D;
                RSAparams.P = P;
                RSAparams.Q = Q;
                RSAparams.DP = DP;
                RSAparams.DQ = DQ;
                RSAparams.InverseQ = IQ;
                RSA.ImportParameters(RSAparams);
                return RSA;
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                binr.Close();
            }
        }

        private static int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)        //expect integer
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();    // data size in next byte
            else
                if (bt == 0x82)
            {
                highbyte = binr.ReadByte();    // data size in next 2 bytes
                lowbyte = binr.ReadByte();
                byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                count = BitConverter.ToInt32(modint, 0);
            }
            else
            {
                count = bt;        // we already have the data size
            }

            while (binr.ReadByte() == 0x00)
            {    //remove high order zeros in data
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);        //last ReadByte wasn't a removed zero, so back up a byte
            return count;
        } 

        ///   
        /// 将pem格式公钥(1024 or 2048)转换为RSAParameters  
        ///   
        /// pem公钥内容  
        /// 转换得到的RSAParamenters  
        public static RSAParameters ConvertFromPemPublicKey(string pemFileConent)
        {
            if (string.IsNullOrEmpty(pemFileConent))
            {
                throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
            }
            pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
            byte[] keyData = Convert.FromBase64String(pemFileConent);
            bool keySize1024 = (keyData.Length == 162);
            bool keySize2048 = (keyData.Length == 294);
            if (!(keySize1024 || keySize2048))
            {
                throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
            }
            byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
            var pemPublicExponent = new byte[3];
            Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
            Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
            var para = new RSAParameters { Modulus = pemModulus, Exponent = pemPublicExponent };
            byte[] sss = para.Modulus;



            return para;
        }
    }
}

你可能感兴趣的:(C#)