C# Rsa加密(私钥加密、公钥解密、密钥格式转换、支持超大长度分段加密)

原文:C# Rsa加密(私钥加密、公钥解密、密钥格式转换、支持超大长度分段加密) - 程序员徐坤 - 博客园 

 

此为工具类,这个和java版本的加密对比过了,结果是一样的,代码赋值黏贴直接用,不多比比,直接上代码(需要在nuget上寻找"Portable.BouncyCastle"包安装):

  (java端有个和c#端不一样的地方,base64编码有好几套,有时候对不上大概率是base64那边的问题)

 

  1 using Org.BouncyCastle.Asn1.Pkcs;
  2 using Org.BouncyCastle.Asn1.X509;
  3 using Org.BouncyCastle.Crypto;
  4 using Org.BouncyCastle.Crypto.Parameters;
  5 using Org.BouncyCastle.Math;
  6 using Org.BouncyCastle.Pkcs;
  7 using Org.BouncyCastle.Security;
  8 using Org.BouncyCastle.X509;
  9 using System;
 10 using System.IO;
 11 using System.Security.Cryptography;
 12 using System.Text;
 13 using System.Xml;
 14 
 15 public class RSAUtil
 16 {
 17     /// <summary>
 18     /// 生成公钥与私钥方法
 19     /// </summary>
 20     /// <returns></returns>
 21     public static string[] CreateKey(KeyType keyType, KeySize keySize)
 22     {
 23         try
 24         {
 25             string[] sKeys = new string[2];
 26             RSACryptoServiceProvider rsa = new RSACryptoServiceProvider((int)keySize);
 27             switch (keyType)
 28             {
 29                 case KeyType.XML:
 30                     {
 31                         //私钥
 32                         sKeys[0] = rsa.ToXmlString(true);
 33                         //公钥
 34                         sKeys[1] = rsa.ToXmlString(false);
 35                     }
 36                     break;
 37                 case KeyType.PKS8:
 38                     {
 39                         sKeys[0] = rsa.ToXmlString(true);
 40                         //公钥
 41                         sKeys[1] = rsa.ToXmlString(false);
 42 
 43                         //JAVA私钥
 44                         sKeys[0] = RSAPrivateKeyDotNet2Java(sKeys[0]);
 45                         //JAVA公钥
 46                         sKeys[1] = RSAPublicKeyDotNet2Java(sKeys[1]);
 47                     }
 48                     break;
 49                 default:
 50                     break;
 51             }
 52             return sKeys;
 53         }
 54         catch (Exception ex)
 55         {
 56             return null;
 57         }
 58     }
 59 
 60     /// <summary>
 61     /// 密钥类型
 62     /// </summary>
 63     public enum KeyType
 64     {
 65         /// <summary>
 66         /// xml类型
 67         /// </summary>
 68         XML,
 69 
 70         /// <summary>
 71         /// pks8类型
 72         /// </summary>
 73         PKS8
 74     }
 75 
 76     /// <summary>
 77     /// 密钥尺寸(一般都是1024位的)
 78     /// </summary>
 79     public enum KeySize
 80     { 
 81         SMALL = 1024,
 82         BIG = 2048
 83     }
 84 
 85 
 86     /// <summary>
 87     /// RSA私钥格式转换,.net->java
 88     /// </summary>
 89     /// <param name="privateKey">.net生成的私钥</param>
 90     /// <returns></returns>
 91     public static string RSAPrivateKeyDotNet2Java(string privateKey)
 92     {
 93         XmlDocument doc = new XmlDocument();
 94         doc.LoadXml(privateKey);
 95         BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
 96         BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
 97         BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
 98         BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
 99         BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
100         BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
101         BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
102         BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));
103 
104         RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
105 
106         PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
107         byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
108         return Convert.ToBase64String(serializedPrivateBytes);
109 
110     }
111 
112     /// <summary>
113     /// RSA公钥格式转换,.net->java
114     /// </summary>
115     /// <param name="publicKey">.net生成的公钥</param>
116     /// <returns></returns>
117     public static string RSAPublicKeyDotNet2Java(string publicKey)
118     {
119         XmlDocument doc = new XmlDocument();
120         doc.LoadXml(publicKey);
121         BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
122         BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
123         RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
124 
125         SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
126         byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
127         return Convert.ToBase64String(serializedPublicBytes);
128     }
129 
130 
131     /// <summary>
132     /// RSA私钥格式转换,java->.net
133     /// </summary>
134     /// <param name="privateKey">java生成的RSA私钥</param>
135     /// <returns></returns>
136     public static string RSAPrivateKeyJavaToDotNet(string privateKey)
137     {
138         RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
139 
140         return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
141             Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
142             Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
143             Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
144             Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
145             Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
146             Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
147             Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
148             Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
149 
150     }
151 
152     /// <summary>
153     /// RSA公钥格式转换,java->.net
154     /// </summary>
155     /// <param name="publicKey">java生成的公钥</param>
156     /// <returns></returns>
157     public static string RSAPublicKeyJavaToDotNet(string publicKey)
158     {
159         RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
160         return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
161             Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
162             Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
163     }
164 
165 
166     /// <summary>
167     /// 最大加密长度
168     /// </summary>
169     private const int MAX_ENCRYPT_BLOCK = 245;
170 
171     /// <summary>
172     /// 最大解密长度
173     /// </summary>
174     private const int MAX_DECRYPT_BLOCK = 256;
175 
176 
177     /// <summary>
178     /// 用私钥给数据进行RSA加密
179     /// </summary>
180     /// <param name="xmlPrivateKey"></param>
181     /// <param name="strEncryptString"></param>
182     /// <returns></returns>
183     public static string PrivateKeyEncrypt(string xmlPrivateKey, string strEncryptString)
184     {
185         //加载私钥
186         RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();
187         privateRsa.FromXmlString(xmlPrivateKey);
188 
189         //转换密钥
190         AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);
191         IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding"); //使用RSA/ECB/PKCS1Padding格式
192 
193         c.Init(true, keyPair.Private);//第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
194         byte[] dataToEncrypt = Encoding.UTF8.GetBytes(strEncryptString);//获取字节
195 
196         byte[] cache;
197         int time = 0;//次数
198         int inputLen = dataToEncrypt.Length;
199         int offSet = 0;
200 
201         MemoryStream outStream = new MemoryStream();
202         while (inputLen - offSet > 0)
203         {
204             if (inputLen - offSet > MAX_ENCRYPT_BLOCK)
205             {
206                 cache = c.DoFinal(dataToEncrypt, offSet, MAX_ENCRYPT_BLOCK);
207             }
208             else
209             {
210                 cache = c.DoFinal(dataToEncrypt, offSet, inputLen - offSet);
211             }
212             //写入
213             outStream.Write(cache, 0, cache.Length);
214 
215             time++;
216             offSet = time * MAX_ENCRYPT_BLOCK;
217         }
218 
219         byte[] resData = outStream.ToArray();
220 
221         string strBase64 = Convert.ToBase64String(resData);
222         outStream.Close();
223         return strBase64;
224     }
225 
226     /// <summary>
227     /// 用公钥给数据进行RSA解密 
228     /// </summary>
229     /// <param name="xmlPublicKey"> 公钥(XML格式字符串) </param>
230     /// <param name="strDecryptString"> 要解密数据 </param>
231     /// <returns> 解密后的数据 </returns>
232     public static string PublicKeyDecrypt(string xmlPublicKey, string strDecryptString)
233     {
234         //加载公钥
235         RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();
236         publicRsa.FromXmlString(xmlPublicKey);
237         RSAParameters rp = publicRsa.ExportParameters(false);
238 
239         //转换密钥
240         AsymmetricKeyParameter pbk = DotNetUtilities.GetRsaPublicKey(rp);
241 
242         IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
243         //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
244         c.Init(false, pbk);
245 
246         byte[] DataToDecrypt = Convert.FromBase64String(strDecryptString);
247 
248         byte[] cache;
249         int time = 0;//次数
250         int inputLen = DataToDecrypt.Length;
251         int offSet = 0;
252         MemoryStream outStream = new MemoryStream();
253         while (inputLen - offSet > 0)
254         {
255             if (inputLen - offSet > MAX_DECRYPT_BLOCK)
256             {
257                 cache = c.DoFinal(DataToDecrypt, offSet, MAX_DECRYPT_BLOCK);
258             }
259             else
260             {
261                 cache = c.DoFinal(DataToDecrypt, offSet, inputLen - offSet);
262             }
263             //写入
264             outStream.Write(cache, 0, cache.Length);
265 
266             time++;
267             offSet = time * MAX_DECRYPT_BLOCK;
268         }
269         byte[] resData = outStream.ToArray();
270 
271         string strDec = Encoding.UTF8.GetString(resData);
272         return strDec;
273     }
274 
275     /// <summary>
276     /// 签名
277     /// </summary>
278     /// <param name="str">需签名的数据</param>
279     /// <returns>签名后的值</returns>
280     public static string Sign(string str, string privateKey, SignAlgType signAlgType)
281     {
282         //根据需要加签时的哈希算法转化成对应的hash字符节
283         byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
284         byte[] rgbHash = null;
285         switch (signAlgType)
286         {
287             case SignAlgType.SHA256:
288                 {
289                     SHA256CryptoServiceProvider csp = new SHA256CryptoServiceProvider();
290                     rgbHash = csp.ComputeHash(bt);
291                 }
292                 break;
293             case SignAlgType.MD5:
294                 {
295                     MD5CryptoServiceProvider csp = new MD5CryptoServiceProvider();
296                     rgbHash = csp.ComputeHash(bt);
297                 }
298                 break;
299             case SignAlgType.SHA1:
300                 {
301                     SHA1 csp = new SHA1CryptoServiceProvider();
302                     rgbHash = csp.ComputeHash(bt);
303                 }
304                 break;
305             default:
306                 break;
307         }
308         RSACryptoServiceProvider key = new RSACryptoServiceProvider();
309         key.FromXmlString(privateKey);
310         RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
311         formatter.SetHashAlgorithm(signAlgType.ToString());//此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
312         byte[] inArray = formatter.CreateSignature(rgbHash);
313         return Convert.ToBase64String(inArray);
314     }
315 
316     /// <summary>
317     /// 签名验证
318     /// </summary>
319     /// <param name="str">待验证的字符串</param>
320     /// <param name="sign">加签之后的字符串</param>
321     /// <returns>签名是否符合</returns>
322     public static bool Verify(string str, string sign, string publicKey, SignAlgType signAlgType)
323     {
324 
325         byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
326         byte[] rgbHash = null;
327         switch (signAlgType)
328         {
329             case SignAlgType.SHA256:
330                 {
331                     SHA256CryptoServiceProvider csp = new SHA256CryptoServiceProvider();
332                     rgbHash = csp.ComputeHash(bt);
333                 }
334                 break;
335             case SignAlgType.MD5:
336                 {
337                     MD5CryptoServiceProvider csp = new MD5CryptoServiceProvider();
338                     rgbHash = csp.ComputeHash(bt);
339                 }
340                 break;
341             case SignAlgType.SHA1:
342                 {
343                     SHA1 csp = new SHA1CryptoServiceProvider();
344                     rgbHash = csp.ComputeHash(bt);
345                 }
346                 break;
347             default:
348                 break;
349         }
350         RSACryptoServiceProvider key = new RSACryptoServiceProvider();
351         key.FromXmlString(publicKey);
352         RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
353         deformatter.SetHashAlgorithm(signAlgType.ToString());
354         byte[] rgbSignature = Convert.FromBase64String(sign);
355         if (deformatter.VerifySignature(rgbHash, rgbSignature))
356             return true;
357         return false;
358     }
359 
360     /// <summary>
361     /// 签名算法类型
362     /// </summary>
363     public enum SignAlgType
364     {
365         /// <summary>
366         /// sha256
367         /// </summary>
368         SHA256,
369 
370         /// <summary>
371         /// md5
372         /// </summary>
373         MD5,
374 
375         /// <summary>
376         /// sha1
377         /// </summary>
378         SHA1
379     }
380 }

 

//公钥分段加密

    /// <summary>
    /// 最大加密长度
    /// </summary>
    private const int MAX_ENCRYPT_BLOCK = 117;

/// <summary>
/// 用公钥给数据进行RSA加密
/// </summary>
/// <param name="xmlPublicKey"> 公钥(XML格式字符串) </param>
/// <param name="strDecryptString"> 要加密数据 </param>
/// <returns>加密后的数据 </returns>
public static string PublicKeyEncrypt(string xmlPublicKey, string strDecryptString)
{
    //加载公钥
    RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider(); 
    publicRsa.FromXmlString(xmlPublicKey);
    RSAParameters rp = publicRsa.ExportParameters(false);
    //转换密钥
    AsymmetricKeyParameter pbk = DotNetUtilities.GetRsaPublicKey(rp);
    IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
    //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
    cipher.Init(true, pbk);

    byte[] DataToDecrypt = Encoding.UTF8.GetBytes(strDecryptString);

    int inputLen = DataToDecrypt.Length;
    MemoryStream outStream = new MemoryStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;//次数   
    while (inputLen - offSet > 0)
    {
        if (inputLen - offSet > MAX_ENCRYPT_BLOCK)
        {
            cache = cipher.DoFinal(DataToDecrypt, offSet, MAX_ENCRYPT_BLOCK);
        }
        else
        {
            cache = cipher.DoFinal(DataToDecrypt, offSet, inputLen - offSet);
        }
        //写入
        outStream.Write(cache, 0, cache.Length);

        i++;
        offSet = i * MAX_ENCRYPT_BLOCK;
    }
    byte[] resData = outStream.ToArray();

    string strDec =Convert.ToBase64String(resData); //Encoding.UTF8.GetString(resData);
    return strDec;
}

 

posted @ 2025-07-31 15:45  酒醉后的疯言疯语  阅读(155)  评论(0)    收藏  举报