C# RSA非对称加密实现
RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。
正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
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
|
这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest,AdiShamir 和Leonard Adleman。早在1973年,英国国家通信总局的数学家Clifford Cocks就发现了类似的算法。但是他的发现被列为绝密,直到1998年才公诸于世。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n,e1),(n,e2)就是密钥对。其中(n,e1)为公钥,(n,e2)为私钥。[1]
RSA加解密的算法完全相同,设A为明文,B为密文,则:A=B^e2 mod n;B=A^e1 mod n;(公钥加密体制中,一般用公钥加密,私钥解密)
e1和e2可以互换使用,即:
A=B^e1 mod n;B=A^e2 mod n;
以下是c#实现:
1 public ActionResult TestRSA() 2 { 3 var str = GenerateKeys(); 4 string source = EncryptString("xuxzx", str[1]); 5 6 return Content(DecryptString(source, str[0])); 7 } 8 9 10 /// <summary> 11 /// generate private key and public key arr[0] for private key arr[1] for public key 12 /// </summary> 13 /// <returns></returns> 14 public static string[] GenerateKeys() 15 { 16 string[] sKeys = new String[2]; 17 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 18 sKeys[0] = rsa.ToXmlString(true); //private 19 sKeys[1] = rsa.ToXmlString(false);//public 20 return sKeys; 21 } 22 23 /// <summary> 24 /// RSA Encrypt 25 /// </summary> 26 /// <param name="sSource" >Source string</param> 27 /// <param name="sPublicKey" >public key</param> 28 /// <returns></returns> 29 public string EncryptString(string sSource, string sPublicKey) 30 { 31 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 32 string plaintext = sSource; 33 rsa.FromXmlString(sPublicKey); 34 byte[] cipherbytes; 35 byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false); 36 cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(plaintext), false); 37 StringBuilder sbString = new StringBuilder(); 38 for (int i = 0; i < cipherbytes.Length; i++) 39 { 40 sbString.Append(cipherbytes[i] + ","); 41 } 42 return sbString.ToString(); 43 } 44 45 /// <summary> 46 /// RSA Decrypt 47 /// </summary> 48 /// <param name="sSource">Source string</param> 49 /// <param name="sPrivateKey">Private Key</param> 50 /// <returns></returns> 51 public string DecryptString(String sSource, string sPrivateKey) 52 { 53 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 54 rsa.FromXmlString(sPrivateKey); 55 byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false); 56 string[] sBytes = sSource.Split(','); 57 for (int j = 0; j < sBytes.Length; j++) 58 { 59 if (sBytes[j] != "") 60 { 61 byteEn[j] = Byte.Parse(sBytes[j]); 62 } 63 } 64 byte[] plaintbytes = rsa.Decrypt(byteEn, false); 65 return Encoding.UTF8.GetString(plaintbytes); 66 }