C#实现RSA加密解密

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。
RSA的缺点:

    • 产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。

    • 分组长度太大,为保证安全性,n 至少也要 600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048bits长的密钥,其他实体使用1024比特的密钥。C)RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。

保密级别对称密钥长度(bit)RSA密钥长度(bit)ECC密钥长度(bit)保密年限
80 80 1024 160 2010
112 112 2048 224 2030
128 128 3072 256 2040
192 192 7680 384 2080
256 256 15360 512 2120

C#中RSA的相关操作

  • 生成公钥和私钥
    public class RSASecretKey
        {
            public RSASecretKey() { }
            public RSASecretKey(string privateKey, string publicKey)
            {
                PrivateKey = privateKey;
                PublicKey = publicKey;
            }
            public string PublicKey { get; set; }
            public string PrivateKey { get; set; }
            public override string ToString()
            {
                return string.Format(
                    "PrivateKey: {0}\r\nPublicKey: {1}", PrivateKey, PublicKey);
            }
    
            /// <summary>
            /// 生成公钥私钥
            /// </summary>
            /// <param name="keySize">the size of the key,must from 384 bits to 16384 bits in increments of 8 </param>
            /// <returns></returns>
            public RSASecretKey GenerateRSASecretKey(int keySize)
            {
                RSASecretKey rsaKey = new RSASecretKey();
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize))
                {
                    rsaKey.PrivateKey = rsa.ToXmlString(true);
                    rsaKey.PublicKey = rsa.ToXmlString(false);
                }
                return rsaKey;
            }
            
        }

     

  • 实现公钥加密私钥解密
        public class RSAHelper
        {
            /// <summary>
            /// 加密
            /// </summary>
            /// <param name="xmlPublicKey"></param>
            /// <param name="content"></param>
            /// <returns></returns>
            public string RSAEncrypt(string xmlPublicKey, string content)
            {
                string encryptedContent = string.Empty;
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(xmlPublicKey);
                    byte[] encryptedData = rsa.Encrypt(Encoding.Default.GetBytes(content), false);
                    encryptedContent = Convert.ToBase64String(encryptedData);
                }
                return encryptedContent;
            }
            /// <summary>
            /// 解密
            /// </summary>
            /// <param name="xmlPrivateKey"></param>
            /// <param name="content"></param>
            /// <returns></returns>
            public string RSADecrypt(string xmlPrivateKey, string content)
            {
                string decryptedContent = string.Empty;
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(xmlPrivateKey);
                    byte[] decryptedData = rsa.Decrypt(Convert.FromBase64String(content), false);
                    decryptedContent = Encoding.GetEncoding("gb2312").GetString(decryptedData);
                }
                return decryptedContent;
            }
    
    
        }

    密钥格式的转换

    C#中RSA公钥和私钥的格式都是XML的,而在其他语言如java中,生成的RSA密钥就是普通的Base64字符串,所以需要将C#xml格式的密钥转换成普通的Base64字符串,同时也要实现Base64密钥字符串生成C#中xml格式的密钥.
    安装 BouncyCastle 这个Nuget包
    PM > Install-Package BouncyCastle
    BouncyCastle项目网址
    BouncyCastlegithub地址
    构造一个RSAKeyConventer类

        using System;
        using System.Security.Cryptography;
        using Org.BouncyCastle.Asn1.Pkcs;
        using Org.BouncyCastle.Math;
        using Org.BouncyCastle.Pkcs;
        using Org.BouncyCastle.Asn1.X509;
        using Org.BouncyCastle.X509;
        using Org.BouncyCastle.Security;
        using Org.BouncyCastle.Crypto.Parameters;
    
        public class RSAKeyConverter
        {
            /// <summary>
            /// xml private key -> base64 private key string
            /// </summary>
            /// <param name="xmlPrivateKey"></param>
            /// <returns></returns>
            public static string FromXmlPrivateKey(string xmlPrivateKey)
            {
                string result = string.Empty;
                using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(xmlPrivateKey);
                    RSAParameters param = rsa.ExportParameters(true);
                    RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(
                        new BigInteger(1, param.Modulus), new BigInteger(1, param.Exponent),
                        new BigInteger(1, param.D), new BigInteger(1, param.P),
                        new BigInteger(1, param.Q), new BigInteger(1, param.DP),
                        new BigInteger(1, param.DQ), new BigInteger(1, param.InverseQ));
                    PrivateKeyInfo privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
                   
                    result = Convert.ToBase64String(privateKey.ToAsn1Object().GetEncoded());
                }
                return result;
            }
    
            /// <summary>
            /// xml public key -> base64 public key string
            /// </summary>
            /// <param name="xmlPublicKey"></param>
            /// <returns></returns>
            public static string FromXmlPublicKey(string xmlPublicKey)
            {
                string result = string.Empty;
                using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(xmlPublicKey);
                    RSAParameters p = rsa.ExportParameters(false);
                    RsaKeyParameters keyParams = new RsaKeyParameters(
                        false, new BigInteger(1,p.Modulus), new BigInteger(1, p.Exponent));
                    SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyParams);
                    result = Convert.ToBase64String(publicKeyInfo.ToAsn1Object().GetEncoded());
                }
                return result;
            }
    
            /// <summary>
            /// base64 private key string -> xml private key
            /// </summary>
            /// <param name="privateKey"></param>
            /// <returns></returns>
            public static string ToXmlPrivateKey(string privateKey)
            {
                RsaPrivateCrtKeyParameters privateKeyParams =
                    PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)) as RsaPrivateCrtKeyParameters;
                using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    RSAParameters rsaParams = new RSAParameters()
                    {
                        Modulus = privateKeyParams.Modulus.ToByteArrayUnsigned(),
                        Exponent = privateKeyParams.PublicExponent.ToByteArrayUnsigned(),
                        D = privateKeyParams.Exponent.ToByteArrayUnsigned(),
                        DP = privateKeyParams.DP.ToByteArrayUnsigned(),
                        DQ = privateKeyParams.DQ.ToByteArrayUnsigned(),
                        P = privateKeyParams.P.ToByteArrayUnsigned(),
                        Q = privateKeyParams.Q.ToByteArrayUnsigned(),
                        InverseQ = privateKeyParams.QInv.ToByteArrayUnsigned()
                    };
                    rsa.ImportParameters(rsaParams);
                    return rsa.ToXmlString(true);
                }
            }
    
            /// <summary>
            /// base64 public key string -> xml public key
            /// </summary>
            /// <param name="pubilcKey"></param>
            /// <returns></returns>
            public static string ToXmlPublicKey(string pubilcKey)
            {
                RsaKeyParameters p = 
                    PublicKeyFactory.CreateKey(Convert.FromBase64String(pubilcKey)) as RsaKeyParameters;
                using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    RSAParameters rsaParams = new RSAParameters
                    {
                        Modulus = p.Modulus.ToByteArrayUnsigned(),
                        Exponent = p.Exponent.ToByteArrayUnsigned()
                    };
                    rsa.ImportParameters(rsaParams);
                    return rsa.ToXmlString(false);
                }
            }
        }

     

posted @ 2019-12-23 22:10  caiyitao  阅读(2344)  评论(0编辑  收藏  举报