添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文主要介绍如何使用 .Net 自带 API 结合 BouncyCastle 类库实现 RSA 加密和解密,密钥生成和密钥格式转换。

一、RSA介绍

RSA 加密算法是 1977 年由 Ron Rivest Adi Shamirh Len Adleman 在(美国麻省理工学院)开发的。 RSA 取名来自开发他们三者的名字。

RSA 加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙。因为加密的钥匙是公开的,所又称 公钥 ,解密的钥匙是不公开的,所以称为 私钥

RSA 是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

RSA 的缺点主要有:

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

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

RSA 密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。

对称密钥长度(bit) RSA密钥长度(bit) ECC密钥长度(bit) 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> /// 生成`RSA`密钥 /// </summary> /// <param name="keySize">密钥的大小,从384位到16384位,每8位递增 </param> /// <returns></returns> 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;

2.2 公钥加密/私钥解密

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;
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;

2.3 密钥格式转换

C#RSA公钥和私钥的格式都是XML的,而在其他语言如java中,生成的RSA密钥就是普通的Base64字符串,所以需要将C# xml格式的密钥转换成普通的Base64字符串,同时也要实现Base64密钥字符串生成C# xml格式的密钥。

安装 BouncyCastle 这个NugetPM > 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;
    namespace RSA
        public class RSAKeyConverter
            /// <summary>
            /// 转换"私钥"格式
            /// </summary>
            /// <param name="xmlPrivateKey">xml格式私钥</param>
            /// <returns>base64格式私钥</returns>
            public static string ToBase64PrivateKey(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>
            /// 转换"公钥"格式
            /// </summary>
            /// <param name="xmlPublicKey">xml格式公钥</param>
            /// <returns>base64格式公钥</returns>
            public static string ToBase64PublicKey(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>
            /// 转换"私钥"格式
            /// </summary>
            /// <param name="privateKey">base64格式私钥</param>
            /// <returns>xml格式私钥</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>
            /// 转换"公钥"格式
            /// </summary>
            /// <param name="pubilcKey">base64格式公钥</param>
            /// <returns>xml格式公钥</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);