最近一個項目中,因為服務端是用的java開發的,客戶端是用的C#,由於通信部分采用到了3DES加密,所以做個記錄,以備以後需要的時候直接用。
這是對方(java)的加密算法,和網上流傳的代碼也差不多(主密鑰直接寫死了,方便測試)
1 package org.zwork.market.mina.msg; 2 3 import java.security.spec.KeySpec; 4 5 import javax.crypto.Cipher; 6 import javax.crypto.SecretKey; 7 import javax.crypto.SecretKeyFactory; 8 import javax.crypto.spec.DESKeySpec; 9 import javax.crypto.spec.DESedeKeySpec; 10 11 import org.slf4j.Logger; 12 import org.slf4j.LoggerFactory; 13 import org.zwork.market.MktContants; 14 15 public class ThreeEncryptDecrypt { 16 17 private static final Logger LOGGER = LoggerFactory.getLogger(ThreeEncryptDecrypt.class); 18 19 // 定義 加密算法,可用 DES,DESede,Blowfish 20 public static final String Algorithm = "DESede"; 21 public static String DES = "DES/ECB/NoPadding"; 22 public static String TriDes = "DESede/ECB/NoPadding"; 23 24 // des加密 25 public static byte[] des_crypt(byte key[], byte data[]) { 26 try { 27 KeySpec ks = new DESKeySpec(key); 28 SecretKeyFactory kf = SecretKeyFactory.getInstance("DES"); 29 SecretKey ky = kf.generateSecret(ks); 30 31 Cipher c = Cipher.getInstance(DES); 32 c.init(Cipher.ENCRYPT_MODE, ky); 33 return c.doFinal(data); 34 } catch (Exception e) { 35 LOGGER.error("des_crypt error:", e); 36 return null; 37 } 38 } 39 40 // des解密 41 public static byte[] des_decrypt(byte key[], byte data[]) { 42 43 try { 44 KeySpec ks = new DESKeySpec(key); 45 SecretKeyFactory kf = SecretKeyFactory.getInstance("DES"); 46 SecretKey ky = kf.generateSecret(ks); 47 48 Cipher c = Cipher.getInstance(DES); 49 c.init(Cipher.DECRYPT_MODE, ky); 50 return c.doFinal(data); 51 } catch (Exception e) { 52 LOGGER.error("des_decrypt error:", e); 53 return null; 54 } 55 } 56 57 // 3DES加密 58 public static byte[] trides_crypt(byte key[], byte data[]) { 59 try { 60 byte[] k = new byte[24]; 61 62 int len = data.length; 63 if (data.length % 8 != 0) { 64 len = data.length - data.length % 8 + 8; 65 } 66 byte[] needData = null; 67 if (len != 0) 68 needData = new byte[len]; 69 70 for (int i = 0; i < len; i++) { 71 needData[i] = 0x00; 72 } 73 74 System.arraycopy(data, 0, needData, 0, data.length); 75 76 if (key.length == 16) { 77 System.arraycopy(key, 0, k, 0, key.length); 78 System.arraycopy(key, 0, k, 16, 8); 79 } else { 80 System.arraycopy(key, 0, k, 0, 24); 81 } 82 83 KeySpec ks = new DESedeKeySpec(k); 84 SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede"); 85 SecretKey ky = kf.generateSecret(ks); 86 87 Cipher c = Cipher.getInstance(TriDes); 88 c.init(Cipher.ENCRYPT_MODE, ky); 89 return c.doFinal(needData); 90 } catch (Exception e) { 91 LOGGER.error("trides_crypt error:", e); 92 return null; 93 } 94 95 } 96 97 // 3DES解密 98 public static byte[] trides_decrypt(byte key[], byte data[]) { 99 try { 100 byte[] k = new byte[24]; 101 102 int len = data.length; 103 if (data.length % 8 != 0) { 104 len = data.length - data.length % 8 + 8; 105 } 106 byte[] needData = null; 107 if (len != 0) 108 needData = new byte[len]; 109 110 for (int i = 0; i < len; i++) { 111 needData[i] = 0x00; 112 } 113 114 System.arraycopy(data, 0, needData, 0, data.length); 115 116 if (key.length == 16) { 117 System.arraycopy(key, 0, k, 0, key.length); 118 System.arraycopy(key, 0, k, 16, 8); 119 } else { 120 System.arraycopy(key, 0, k, 0, 24); 121 } 122 KeySpec ks = new DESedeKeySpec(k); 123 SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede"); 124 SecretKey ky = kf.generateSecret(ks); 125 126 Cipher c = Cipher.getInstance(TriDes); 127 c.init(Cipher.DECRYPT_MODE, ky); 128 return c.doFinal(needData); 129 } catch (Exception e) { 130 LOGGER.error("trides_decrypt error:", e); 131 return null; 132 } 133 } 134 135 public static String getPass(String source) { 136 byte[] data= hexToBytes(source); 137 byte[] key ="111111111111111111111111111a1.1.".getBytes(); 138 String result = byte2hex(trides_decrypt(key, data)).toUpperCase(); 139 return result.substring(2, 8); 140 } 141 142 public static String byte2hex(byte[] data) { 143 StringBuffer sb = new StringBuffer(); 144 for (int i = 0; i < data.length; i++) { 145 String temp = Integer.toHexString(((int) data[i]) & 0xFF); 146 for (int t = temp.length(); t < 2; t++) { 147 sb.append("0"); 148 } 149 sb.append(temp); 150 } 151 return sb.toString(); 152 } 153 154 public static byte[] hexToBytes(String str) { 155 if (str == null) { 156 return null; 157 } else if (str.length() < 2) { 158 return null; 159 } else { 160 int len = str.length() / 2; 161 byte[] buffer = new byte[len]; 162 for (int i = 0; i < len; i++) { 163 buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16); 164 } 165 return buffer; 166 } 167 } 168 }
因為客戶端只負責數據加密,所以我這裡只寫了加密的部分。由於java和C#語言很相似,所以我就仿這他們給的java代碼改成C#的,當然也在網上參考了一些代碼,不過中間還是出現了些問題,比如C#不支持弱密鑰(把密鑰弄復雜點),因為沒注意大小寫造成加密結果不一致等等。編程這東西一個點都能讓整個系統崩潰,所以小細節很重要!!!
1 public class DESHelper 2 { 3 /// <summary> 4 /// 將密碼轉成直接數組 5 /// </summary> 6 /// <param name="str"></param> 7 /// <returns></returns> 8 public static byte[] HexToBytes(String str) 9 { 10 if (str == null) 11 { 12 return null; 13 } 14 else if (str.Length < 2) 15 { 16 return null; 17 } 18 else 19 { 20 int len = str.Length / 2; 21 byte[] buffer = new byte[len]; 22 for (int i = 0; i < len; i++) 23 { 24 var temp = str.Substring(i * 2, 2); 25 buffer[i] = (byte)Convert.ToInt32(temp, 16); 26 } 27 return buffer; 28 } 29 } 30 /// <summary> 31 /// 3DES加密 32 /// </summary> 33 /// <param name="key"></param> 34 /// <param name="data"></param> 35 /// <returns></returns> 36 public static byte[] GetDes3EncryptedText(byte[] key, byte[] data) 37 { 38 byte[] k = new byte[24]; 39 int len = data.Length; 40 if (data.Length % 8 != 0) 41 { 42 len = data.Length - data.Length % 8 + 8; 43 } 44 byte[] needData = null; 45 if (len != 0) 46 needData = new byte[len]; 47 48 for (int i = 0; i < len; i++) 49 { 50 needData[i] = 0x00; 51 } 52 53 Buffer.BlockCopy(data, 0, needData, 0, data.Length); 54 55 if (key.Length == 16) 56 { 57 Buffer.BlockCopy(key, 0, k, 0, key.Length); 58 Buffer.BlockCopy(key, 0, k, 16, 8); 59 } 60 else 61 { 62 Buffer.BlockCopy(key, 0, k, 0, 24); 63 } 64 65 var des3 = new TripleDESCryptoServiceProvider(); 66 des3.Key = k; 67 des3.Mode = CipherMode.ECB; 68 des3.Padding = PaddingMode.Zeros; 69 70 using (MemoryStream ms = new MemoryStream()) 71 using (CryptoStream cs = new CryptoStream(ms, des3.CreateEncryptor(), CryptoStreamMode.Write)) 72 { 73 cs.Write(data, 0, data.Length); 74 cs.FlushFinalBlock(); 75 return ms.ToArray(); 76 } 77 } 78 79 /// <summary> 80 /// 將加密結果轉成字符串 81 /// </summary> 82 /// <param name="data"></param> 83 /// <returns></returns> 84 public static String GetByte2Hex(byte[] data) 85 { 86 StringBuilder sb = new StringBuilder(); 87 for (int i = 0; i < data.Length; i++) 88 { 89 String temp = string.Format("{0:X}", ((int)data[i]) & 0xFF); 90 for (int t = temp.Length; t < 2; t++) 91 { 92 sb.Append("0"); 93 } 94 sb.Append(temp); 95 } 96 return sb.ToString(); 97 } 98 }