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} PublicKey: {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); } } }