本文主要介绍如何使用
.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
这个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;
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);