java與.net rsa加密互通


最近遇到一個項目需要做單點,用戶方是采用java rsa公鑰加密傳遞信息的,我這邊是.net使用私鑰解密。而對方提供的解密源碼是java版本的,並且也沒有做過與.net平台的單點對接。

於是在網上找到了如下版本的c# 版本rsa私鑰解密方法

 1         /// <summary>  
 2         /// RSA的解密函數  
 3         /// </summary>  
 4         /// <param name="xmlPrivateKey">私鑰</param>  
 5         /// <param name="decryptString">待解密的字符串</param>  
 6         /// <returns></returns>  
 7         public string RSADecrypt(string xmlPrivateKey, string decryptString)
 8         {
 9                 byte[] PlainTextBArray;//解密前字節流
10                 byte[] DypherTextBArray;//解密后字節流
11                 string Result = "";
12                 System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
13                 rsa.FromXmlString(xmlPrivateKey);
14                 PlainTextBArray = Convert.FromBase64String(decryptString);
15                 DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
16                 Result = Encoding.UTF8.GetString(DypherTextBArray);
17                 return Result;
18         }

拿過來之后把私鑰和帶解密字符串傳入,發現報錯,於是研究發現,c#的rsa解密私鑰是xml格式的,而對方提供的是base64字符串,所以需要先把私鑰轉成xml格式,

轉換無法在c#中進行,需要打開在java下面轉換,可以下個exclipse把如下代碼復制進去就行。

  1 package com;
  2 
  3 import java.security.KeyFactory;
  4 import java.security.PublicKey;
  5 import java.security.interfaces.RSAPrivateCrtKey;
  6 import java.security.interfaces.RSAPublicKey;
  7 import java.security.spec.PKCS8EncodedKeySpec;
  8 import java.security.spec.X509EncodedKeySpec;
  9 //import org.castor.util.Base64Decoder;
 10 //import org.castor.util.Base64Encoder;
 11 
 12 public class test {
 13 
 14 public static void main(String[] args) 
 15 {
 16 String tes="MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAL8z2QlXCL6w7rvY0Gbl8ARtQSXY+pEW5hlUHlmspqHt4k8/SkoF796gDqk4yyOcoWhkZWLPPugK35Mn7V+m5Jyfu8C0gVKOfWOA8A0T4hxV2ThAoMUq7QtB2K6s9AoumrxDfAkMBbsXEHYwfD/hxr/3DQ3lUvSFB6BnhiHEOyzpAgMBAAECgYEAol/9qRjorEjF9XEjSr9rHddKxEGIST8RGeF+BNnCiTHkRziQdlykYIO876jzmsKhsG3STB+EZLsXM3ls9RZefcsPF5mLOCSOCow3DikfCtAy4hntsU9JwpuYE0V4A+Sgfd24fatqbu+JxE2nvpSbAPczDOgBFPNfYBkhMiuZ/iECQQDzUeq7lFcIE4uWhRGveVFjNAGuSsW+q9GOwO7tS5YwuAIQ2M+XgYGRFo8xMC6V/9SfqJtmSU1zk72pMlYufIqHAkEAySqkcKbWuobq5I9KSQISq2qCuGKtj/iUFho4PCD1YxhnQ7gcHA4OpS1dRFjtXJYQPTX9be+mmypsCFIyofE5DwJBAPGZ20wahTh9v9Lbmq3z9n5ce3bGxAcJsHDg3d09eooxi8uSnL5BV5frII+k2f0TI9rMnlE4Y/FpN5+zXaOXAi0CQQCs3Aqfjo23jJWtPv/LSo+2YnjfblPMAgNmFrO532xc8axSgZMN/HpTL28UewHD7GMZ5hnWbPcSIFrir5c4luq7AkEAi90WdnZVPxtSTqkkLYbnh4Ro2WhdwRjkfyBxBZZx8hfaM6MfLPi3A0rw9DPOSB4M/BMchtEh3bXuI7bue2tG+A==";
 17 byte[] temp=b64decode(tes);
 18 String ver=getRSAPrivateKeyAsNetFormat(temp);//轉換私鑰
 19 
 20 String tes1="MIGfMA0GCSqGSIb4DQEBAQUAA4GNADCBiQKBgQC/M9kJVwi+sO672NBm5fAEbUEl2PqRFuYZVB5ZrKah7eJPP0pKBe/eoA6pOMsjnKFoZGVizz7oCt+TJ+1fpuScn7vAtIFSjn1jgPANE+IcVdk4QKDFKu0LQdiurPQKLpq8Q3wJDAW7FxB2MHw/4ca/9w0N5VL0hQegZ4YhxDss6QIDAQAB";
 21 byte[] temp1=b64decode(tes1);
 22 String ver1=getRSAPublicKeyAsNetFormat(temp1);//轉換公鑰
 23 //String temp2= encodePublicKeyToXml(temp1);
 24 
 25 }
 26 
 27 private static String getRSAPrivateKeyAsNetFormat(byte[] encodedPrivkey) {
 28 try {
 29 StringBuffer buff = new StringBuffer(1024);
 30 
 31 PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
 32 encodedPrivkey);
 33 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
 34 RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
 35 .generatePrivate(pvkKeySpec);
 36 
 37 buff.append("<RSAKeyValue>");
 38 buff.append("<Modulus>"
 39 + b64encode(removeMSZero(pvkKey.getModulus().toByteArray()))
 40 + "</Modulus>");
 41 
 42 buff.append("<Exponent>"
 43 + b64encode(removeMSZero(pvkKey.getPublicExponent()
 44 .toByteArray())) + "</Exponent>");
 45 
 46 buff.append("<P>"
 47 + b64encode(removeMSZero(pvkKey.getPrimeP().toByteArray()))
 48 + "</P>");
 49 
 50 buff.append("<Q>"
 51 + b64encode(removeMSZero(pvkKey.getPrimeQ().toByteArray()))
 52 + "</Q>");
 53 
 54 buff.append("<DP>"
 55 + b64encode(removeMSZero(pvkKey.getPrimeExponentP()
 56 .toByteArray())) + "</DP>");
 57 
 58 buff.append("<DQ>"
 59 + b64encode(removeMSZero(pvkKey.getPrimeExponentQ()
 60 .toByteArray())) + "</DQ>");
 61 
 62 buff.append("<InverseQ>"
 63 + b64encode(removeMSZero(pvkKey.getCrtCoefficient()
 64 .toByteArray())) + "</InverseQ>");
 65 
 66 buff.append("<D>"
 67 + b64encode(removeMSZero(pvkKey.getPrivateExponent()
 68 .toByteArray())) + "</D>");
 69 buff.append("</RSAKeyValue>");
 70 
 71 return buff.toString().replaceAll("[ \t\n\r]", "");
 72 } catch (Exception e) {
 73 System.err.println(e);
 74 return null;
 75 }
 76 }
 77 
 78 private static String getRSAPublicKeyAsNetFormat(byte[] encodedPrivkey) {
 79 try {
 80 StringBuffer buff = new StringBuffer(1024);
 81 
 82 PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(encodedPrivkey);
 83 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
 84 RSAPublicKey pukKey=(RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(encodedPrivkey));
 85 // RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(pvkKeySpec);
 86 //PublicKey publicKey =KeyFactory.getInstance("RSA").generatePublic(pvkKeySpec);
 87 buff.append("<RSAKeyValue>");
 88 buff.append("<Modulus>"
 89 + b64encode(removeMSZero(pukKey.getModulus().toByteArray()))
 90 + "</Modulus>");
 91 buff.append("<Exponent>"
 92 + b64encode(removeMSZero(pukKey.getPublicExponent()
 93 .toByteArray())) + "</Exponent>");
 94 buff.append("</RSAKeyValue>");
 95 return buff.toString().replaceAll("[ \t\n\r]", "");
 96 } catch (Exception e) {
 97 System.err.println(e);
 98 return null;
 99 }
100 }
101 public static String encodePublicKeyToXml(PublicKey key) {
102 if (!RSAPublicKey.class.isInstance(key)) {
103 return null;
104 }
105 RSAPublicKey pubKey = (RSAPublicKey) key;
106 StringBuilder sb = new StringBuilder();
107 sb.append("<RSAKeyValue>");
108 sb.append("<Modulus>")
109 .append(Base64.encode(pubKey.getModulus().toByteArray()))
110 .append("</Modulus>");
111 sb.append("<Exponent>")
112 .append(Base64.encode(pubKey.getPublicExponent()
113 .toByteArray())).append("</Exponent>");
114 sb.append("</RSAKeyValue>");
115 return sb.toString();
116 }
117 
118 private static byte[] removeMSZero(byte[] data) {
119 byte[] data1;
120 int len = data.length;
121 if (data[0] == 0) {
122 data1 = new byte[data.length - 1];
123 System.arraycopy(data, 1, data1, 0, len - 1);
124 } else
125 data1 = data;
126 return data1;
127 }
128 private static String b64encode(byte[] data) {
129 
130 String b64str = new String(Base64.encode(data));
131 return b64str;
132 }
133 
134 private static byte[] b64decode(String data) {
135 byte[] decodeData = Base64.decode(data);
136 return decodeData;
137 }
138 }

參考:http://www.cnblogs.com/hvaning/p/3636288.html

現在拿到c#的私鑰了,發現解密還是報錯,又看了下,發現用戶給的加密文本是16進制文本,並不是base64文本,於是寫了個16進制轉字節的方法供調用。

16進制文本轉字節流方法如下

 1  /// <summary>
 2         /// 16進制文本轉字節流
 3         /// </summary>
 4         /// <param name="src">16進制文本</param>
 5         /// <returns></returns>
 6         public byte[] hexStr2ByteArr(string src)
 7         {
 8             int l = src.Length / 2;//2個16進制文本等於一個字節,所以字節數組長度是16進制文本長度的一半
 9             String str;
10             byte[] ret = new byte[l];
11 
12             for (int i = 0; i < l; i++)
13             {
14                 str = src.Substring(i * 2, 2);
15                 ret[i] = Convert.ToByte(str, 16);
16             }
17             return ret;
18         }

然后下一個坑又出來了,rsa解密一次只能128個字節,所以又寫了個循環的方法,每次解密128個字節數組,最終再拼接起來,最終代碼如下:

 1 /// <summary>  
 2         /// RSA的解密函數  
 3         /// </summary>  
 4         /// <param name="xmlPrivateKey">私鑰</param>  
 5         /// <param name="decryptString">待解密的字符串</param>  
 6         /// <returns></returns>  
 7         public string RSADecrypt(string xmlPrivateKey, string decryptString)
 8         {
 9             try
10             {
11                 byte[] PlainTextBArray;
12                 byte[] DypherTextBArray;
13                 string Result = "";
14                 System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
15                 rsa.FromXmlString(xmlPrivateKey);
16                 PlainTextBArray = hexStr2ByteArr(decryptString);
17                 var outlength = PlainTextBArray.Length;
18                 var i = 0;
19                 while (true) {
20                     if (outlength > 128)
21                     {
22                         var aa = new byte[128];
23                         Array.Copy(PlainTextBArray, i, aa, 0, 128);
24                         DypherTextBArray = rsa.Decrypt(aa, false);
25                         Result = Result + Encoding.UTF8.GetString(DypherTextBArray);
26                         outlength = outlength - 128;
27                         i = i + 128;
28                     }
29                     else {
30                         var aa = new byte[outlength];
31                         Array.Copy(PlainTextBArray, i, aa, 0, outlength);
32                         DypherTextBArray = rsa.Decrypt(aa, false);
33                         Result = Result + Encoding.UTF8.GetString(DypherTextBArray);
34                         break;
35                     }   
36                 }
37                 return Result;
38             }
39             catch (Exception ex)
40             {
41                 throw ex;
42             }
43         }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM