RSA公鑰加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。
RSA的缺點:java
產生密鑰很麻煩,受到素數產生技術的限制,於是難以作到一次一密。git
分組長度太大,爲保證安全性,n 至少也要 600bits以上,使運算代價很高,尤爲是速度較慢,較對稱密碼算法慢幾個數量級;且隨着大數分解技術的發展,這個長度還在增長,不利於數據格式的標準化。目前,SET(Secure Electronic Transaction)協議中要求CA採用2048bits長的密鑰,其餘實體使用1024比特的密鑰。C)RSA密鑰長度隨着保密級別提升,增長很快。下表列出了對同一安全級別所對應的密鑰長度。github
保密級別 | 對稱密鑰長度(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 |
struct 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> /// generate RSA secret key /// </summary> /// <param name="keySize">the size of the key,must from 384 bits to 16384 bits in increments of 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; }
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; }
C#中RSA公鑰和私鑰的格式都是XML的,而在其餘語言如java中,生成的RSA密鑰就是普通的Base64字符串,因此須要將C#xml格式的密鑰轉換成普通的Base64字符串,同時也要實現Base64密鑰字符串生成C#中xml格式的密鑰.
安裝 BouncyCastle 這個Nuget包
PM > Install-Package BouncyCastle
BouncyCastle項目網址
BouncyCastlegithub地址
構造一個RSAKeyConventer類算法
namespace RSA { 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); } } } }