最近 一個專案.net 要呼叫JAVA的WEB SERVICE,資料採用3DES加密,涉及到兩種語言3DES一致性的問題, 下面分享一下, 這裡的KEY採用Base64編碼,便用分發,因為Java的Byte範圍為-128至127,c#的Byte範圍是0-255 核心是確定Mode和Padding,關於這兩個的意思可以搜尋3DES演算法相關文章 一個是C#採用CBC Mode,PKCS7 Padding,Java採用CBC Mode,PKCS5Padding Padding, 另一個是C#採用ECB Mode,PKCS7 Padding,Java採用ECB Mode,PKCS5Padding Padding, Java的ECB模式不需要IV 對字元加密時,雙方採用的都是UTF-8編碼
下面是C#程式碼
01./// <summary> 02./// DES3加密解密 03./// </summary> 04.public class Des3 05.{ 06. #region CBC模式** 07. /// <summary> 08. /// DES3 CBC模式加密 09. /// </summary> 10. /// <param name="key">金鑰</param> 11. /// <param name="iv">IV</param> 12. /// <param name="data">明文的byte陣列</param> 13. /// <returns>密文的byte陣列</returns> 14. public static byte[] Des3EncodeCBC( byte[] key, byte[] iv, byte[] data ) 15. { 16. //複製於MSDN 17. try 18. { 19. // Create a MemoryStream. 20. MemoryStream mStream = new MemoryStream(); 21. TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 22. tdsp.Mode = CipherMode.CBC; //預設值 23. tdsp.Padding = PaddingMode.PKCS7; //預設值 24. // Create a CryptoStream using the MemoryStream 25. // and the passed key and initialization vector (IV). 26. CryptoStream cStream = new CryptoStream( mStream, 27. tdsp.CreateEncryptor( key, iv ), 28. CryptoStreamMode.Write ); 29. // Write the byte array to the crypto stream and flush it. 30. cStream.Write( data, 0, data.Length ); 31. cStream.FlushFinalBlock(); 32. // Get an array of bytes from the 33. // MemoryStream that holds the 34. // encrypted data. 35. byte[] ret = mStream.ToArray(); 36. // Close the streams. 37. cStream.Close(); 38. mStream.Close(); 39. // Return the encrypted buffer. 40. return ret; 41. } 42. catch ( CryptographicException e ) 43. { 44. Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 45. return null; 46. } 47. } 48. /// <summary> 49. /// DES3 CBC模式解密 50. /// </summary> 51. /// <param name="key">金鑰</param> 52. /// <param name="iv">IV</param> 53. /// <param name="data">密文的byte陣列</param> 54. /// <returns>明文的byte陣列</returns> 55. public static byte[] Des3DecodeCBC( byte[] key, byte[] iv, byte[] data ) 56. { 57. try 58. { 59. // Create a new MemoryStream using the passed 60. // array of encrypted data. 61. MemoryStream msDecrypt = new MemoryStream( data ); 62. TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 63. tdsp.Mode = CipherMode.CBC; 64. tdsp.Padding = PaddingMode.PKCS7; 65. // Create a CryptoStream using the MemoryStream 66. // and the passed key and initialization vector (IV). 67. CryptoStream csDecrypt = new CryptoStream( msDecrypt, 68. tdsp.CreateDecryptor( key, iv ), 69. CryptoStreamMode.Read ); 70. // Create buffer to hold the decrypted data. 71. byte[] fromEncrypt = new byte[data.Length]; 72. // Read the decrypted data out of the crypto stream 73. // and place it into the temporary buffer. 74. csDecrypt.Read( fromEncrypt, 0, fromEncrypt.Length ); 75. //Convert the buffer into a string and return it. 76. return fromEncrypt; 77. } 78. catch ( CryptographicException e ) 79. { 80. Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 81. return null; 82. } 83. } 84. #endregion 85. #region ECB模式 86. /// <summary> 87. /// DES3 ECB模式加密 88. /// </summary> 89. /// <param name="key">金鑰</param> 90. /// <param name="iv">IV(當模式為ECB時,IV無用)</param> 91. /// <param name="str">明文的byte陣列</param> 92. /// <returns>密文的byte陣列</returns> 93. public static byte[] Des3EncodeECB( byte[] key, byte[] iv, byte[] data ) 94. { 95. try 96. { 97. // Create a MemoryStream. 98. MemoryStream mStream = new MemoryStream(); 99. TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 100. tdsp.Mode = CipherMode.ECB; 101. tdsp.Padding = PaddingMode.PKCS7; 102. // Create a CryptoStream using the MemoryStream 103. // and the passed key and initialization vector (IV). 104. CryptoStream cStream = new CryptoStream( mStream, 105. tdsp.CreateEncryptor( key, iv ), 106. CryptoStreamMode.Write ); 107. // Write the byte array to the crypto stream and flush it. 108. cStream.Write( data, 0, data.Length ); 109. cStream.FlushFinalBlock(); 110. // Get an array of bytes from the 111. // MemoryStream that holds the 112. // encrypted data. 113. byte[] ret = mStream.ToArray(); 114. // Close the streams. 115. cStream.Close(); 116. mStream.Close(); 117. // Return the encrypted buffer. 118. return ret; 119. } 120. catch ( CryptographicException e ) 121. { 122. Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 123. return null; 124. } 125. } 126. /// <summary> 127. /// DES3 ECB模式解密 128. /// </summary> 129. /// <param name="key">金鑰</param> 130. /// <param name="iv">IV(當模式為ECB時,IV無用)</param> 131. /// <param name="str">密文的byte陣列</param> 132. /// <returns>明文的byte陣列</returns> 133. public static byte[] Des3DecodeECB( byte[] key, byte[] iv, byte[] data ) 134. { 135. try 136. { 137. // Create a new MemoryStream using the passed 138. // array of encrypted data. 139. MemoryStream msDecrypt = new MemoryStream( data ); 140. TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 141. tdsp.Mode = CipherMode.ECB; 142. tdsp.Padding = PaddingMode.PKCS7; 143. // Create a CryptoStream using the MemoryStream 144. // and the passed key and initialization vector (IV). 145. CryptoStream csDecrypt = new CryptoStream( msDecrypt, 146. tdsp.CreateDecryptor( key, iv ), 147. CryptoStreamMode.Read ); 148. // Create buffer to hold the decrypted data. 149. byte[] fromEncrypt = new byte[data.Length]; 150. // Read the decrypted data out of the crypto stream 151. // and place it into the temporary buffer. 152. csDecrypt.Read( fromEncrypt, 0, fromEncrypt.Length ); 153. //Convert the buffer into a string and return it. 154. return fromEncrypt; 155. } 156. catch ( CryptographicException e ) 157. { 158. Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 159. return null; 160. } 161. } 162. #endregion 163. /// <summary> 164. /// 類測試 165. /// </summary> 166. public static void Test() 167. { 168. System.Text.Encoding utf8 = System.Text.Encoding.UTF8; 169. //key為abcdefghijklmnopqrstuvwx的Base64編碼 170. byte[] key = Convert.FromBase64String( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" ); 171. byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; //當模式為ECB時,IV無用 172. byte[] data = utf8.GetBytes( "中國ABCabc123" ); 173. System.Console.WriteLine( "ECB模式:" ); 174. byte[] str1 = Des3.Des3EncodeECB( key, iv, data ); 175. byte[] str2 = Des3.Des3DecodeECB( key, iv, str1 ); 176. System.Console.WriteLine( Convert.ToBase64String( str1 ) ); 177. System.Console.WriteLine( System.Text.Encoding.UTF8.GetString( str2 ) ); 178. System.Console.WriteLine(); 179. System.Console.WriteLine( "CBC模式:" ); 180. byte[] str3 = Des3.Des3EncodeCBC( key, iv, data ); 181. byte[] str4 = Des3.Des3DecodeCBC( key, iv, str3 ); 182. System.Console.WriteLine( Convert.ToBase64String( str3 ) ); 183. System.Console.WriteLine( utf8.GetString( str4 ) ); 184. System.Console.WriteLine(); 185. } 186.}
接著是Java程式碼
01.import java.security.Key; 02.import javax.crypto.Cipher; 03.import javax.crypto.SecretKeyFactory; 04.import javax.crypto.spec.DESedeKeySpec; 05.import javax.crypto.spec.IvParameterSpec; 06.import sun.misc.BASE64Decoder; 07.import sun.misc.BASE64Encoder; 08.public class Des3 { 09. public static void main(String[] args) throws Exception { 10. byte[] key=new BASE64Decoder().decodeBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"); 11. byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 }; 12. byte[] data="中國ABCabc123".getBytes("UTF-8"); 13. 14. System.out.println("ECB加密解密"); 15. byte[] str3 = des3EncodeECB(key,data ); 16. byte[] str4 = ees3DecodeECB(key, str3); 17. System.out.println(new BASE64Encoder().encode(str3)); 18. System.out.println(new String(str4, "UTF-8")); 19. System.out.println(); 20. System.out.println("CBC加密解密"); 21. byte[] str5 = des3EncodeCBC(key, keyiv, data); 22. byte[] str6 = des3DecodeCBC(key, keyiv, str5); 23. System.out.println(new BASE64Encoder().encode(str5)); 24. System.out.println(new String(str6, "UTF-8")); 25. } 26. /** 27. * ECB加密,不要IV 28. * @param key 金鑰 29. * @param data 明文 30. * @return Base64編碼的密文 31. * @throws Exception 32. */ 33. public static byte[] des3EncodeECB(byte[] key, byte[] data) 34. throws Exception { 35. Key deskey = null; 36. DESedeKeySpec spec = new DESedeKeySpec(key); 37. SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 38. deskey = keyfactory.generateSecret(spec); 39. Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding"); 40. cipher.init(Cipher.ENCRYPT_MODE, deskey); 41. byte[] bOut = cipher.doFinal(data); 42. return bOut; 43. } 44. /** 45. * ECB解密,不要IV 46. * @param key 金鑰 47. * @param data Base64編碼的密文 48. * @return 明文 49. * @throws Exception 50. */ 51. public static byte[] ees3DecodeECB(byte[] key, byte[] data) 52. throws Exception { 53. Key deskey = null; 54. DESedeKeySpec spec = new DESedeKeySpec(key); 55. SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 56. deskey = keyfactory.generateSecret(spec); 57. Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding"); 58. cipher.init(Cipher.DECRYPT_MODE, deskey); 59. byte[] bOut = cipher.doFinal(data); 60. return bOut; 61. } 62. /** 63. * CBC加密 64. * @param key 金鑰 65. * @param keyiv IV 66. * @param data 明文 67. * @return Base64編碼的密文 68. * @throws Exception 69. */ 70. public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data) 71. throws Exception { 72. Key deskey = null; 73. DESedeKeySpec spec = new DESedeKeySpec(key); 74. SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 75. deskey = keyfactory.generateSecret(spec); 76. Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding"); 77. IvParameterSpec ips = new IvParameterSpec(keyiv); 78. cipher.init(Cipher.ENCRYPT_MODE, deskey, ips); 79. byte[] bOut = cipher.doFinal(data); 80. return bOut; 81. } 82. /** 83. * CBC解密 84. * @param key 金鑰 85. * @param keyiv IV 86. * @param data Base64編碼的密文 87. * @return 明文 88. * @throws Exception 89. */ 90. public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data) 91. throws Exception { 92. Key deskey = null; 93. DESedeKeySpec spec = new DESedeKeySpec(key); 94. SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 95. deskey = keyfactory.generateSecret(spec); 96. Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding"); 97. IvParameterSpec ips = new IvParameterSpec(keyiv); 98. cipher.init(Cipher.DECRYPT_MODE, deskey, ips); 99. byte[] bOut = cipher.doFinal(data); 100. return bOut; 101. }
下面是執行結果
ECB模式:
rmWB4+r9Ug93WI0KAEuMig==
中國ABCabc123
CBC模式:
4aabWF8UFour/vNfnzJrjw==
中國ABCabc123
文章來自:http://blog.csdn.net/sdfkfkd/article/details/6004847 感謝作者的分享。