C# RSA加密解密

Posted you000bbs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# RSA加密解密相关的知识,希望对你有一定的参考价值。

1.解析密钥

/// <summary>
        /// 把二进制密钥解析成RSACryptoServiceProvider
        /// </summary>
        /// <param name="privkey"></param>
        /// <returns></returns>
        private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
        {
            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 -----
                CspParameters CspParameters = new CspParameters();
                CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
                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 ex)
            {
                return null;
            }
            finally
            {
                binr.Close();
            }
        }
        /// <summary>
        /// 二进制解析辅助函数
        /// </summary>
        /// <param name="binr"></param>
        /// <returns></returns>
        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;
        }

2.导出私钥字符串格式

        /// <summary>
        /// 导出RSACryptoServiceProvider对象私钥成XML格式
        /// </summary>
        /// <param name="privatekey"></param>
        /// <returns></returns>
        public static string GetRSAKeyValueXml(string privatekey)
        {
            byte[] data = Convert.FromBase64String(privatekey);
            RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(data);
            return rsa.ToXmlString(true);
        }

3.不可解密的方式加密

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="txt">待加密字符串</param>
        /// <param name="privatekey">私钥</param>
        /// <returns>Base64加案后结果</returns>
        public static string SHA1(string txt, string rsaXML)
        {  
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(rsaXML);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(txt);
            //
            return Convert.ToBase64String(rsa.SignData(data, "SHA1"));
        }

4.普通的加密方式

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="txt">待加密字符串</param>
        /// <param name="privatekey">私钥</param>
        /// <returns>Base64加案后结果</returns>
        public static string Encrypt(string txt, string rsaXML)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(rsaXML);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(txt);
            int MaxBlockSize = rsa.KeySize / 8 - 11;    //加密块最大长度限制

            if (data.Length <= MaxBlockSize)
                return Convert.ToBase64String(rsa.Encrypt(data, false));
            using (MemoryStream PlaiStream = new MemoryStream(data))
            {
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToEncrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
                        Byte[] Cryptograph = rsa.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            } 
        }

5.普通的解密方式

  
        /// <summary>
        /// 解密
        /// </summary> 
        public static string Decrypt(string txt, string rsaXML)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(rsaXML);
            byte[] data = Convert.FromBase64String(txt);
            int MaxBlockSize = rsa.KeySize / 8;    //加密块最大长度限制

            if (data.Length <= MaxBlockSize)
                return System.Text.Encoding.UTF8.GetString(rsa.Decrypt(data, false));
            using (MemoryStream PlaiStream = new MemoryStream(data))
            {
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToEncrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
                        Byte[] Cryptograph = rsa.Decrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return System.Text.Encoding.UTF8.GetString(CrypStream.ToArray());
                }
            } 
        }

 

以上是关于C# RSA加密解密的主要内容,如果未能解决你的问题,请参考以下文章

C# RSA 加密/解密与传输

C#中RSA加密解密和签名与验证的实现

RSA 加密 C#

(转)C#实现RSA非对称加密解密

在 C# 中使用具有正确私钥和公钥对的 RSA 解密时出现错误数据异常

C# BouncyCastle RSA 加密和解密