1. 程式人生 > >Java與Delphi交叉DES加解密的問題

Java與Delphi交叉DES加解密的問題

何為交叉加解密?

——Java加密、Delphi解密,或 Delphi加密、Java解密。

近日,手頭上當前的專案進展到優化、完善階段,其中一點是需要增強服務端與客戶端通訊的安全性,考慮採用對報文進行DES加密的方法來實現。

服務端是Java編寫的,客戶端是Delphi編寫的,原以為兩端各自coding完進行個聯調就OK了,結果發現同樣的明文、金鑰通過Delphi、Java所產生的密文是不同的。

在網上搜索相關資源,得出結論:

原來這是個普遍存在的問題,主要原因是不同的語言在明文的長度不夠8byte倍數時,補充的位元組各不相同所致。

Java和C之間已經有解決方案(http://shirlly.iteye.com/blog/310759

),而Java和Delphi的已由公司牛人於2009-12-10解決,程式碼如下:

Java程式碼  
  1. import java.security.SecureRandom;  
  2. import javax.crypto.Cipher;  
  3. import javax.crypto.SecretKey;  
  4. import javax.crypto.SecretKeyFactory;  
  5. import javax.crypto.spec.DESKeySpec;  
  6. /** 
  7.  * DES加解密,支援與delphi互動(字串編碼需統一為UTF-8) 
  8.  *  
  9.  * @author wym 
  10.  */
  11. publicclass
     DESCipherCrossoverDelphi {  
  12.     /** 
  13.      * 金鑰 
  14.      */
  15.     publicstaticfinal String KEY = "12345678";  
  16.     privatefinalstatic String DES = "DES";  
  17.     /** 
  18.      * 加密 
  19.      *  
  20.      * @param src 
  21.      *            明文(位元組) 
  22.      * @param key 
  23.      *            金鑰,長度必須是8的倍數 
  24.      * @return 密文(位元組) 
  25.      * @throws Exception
     
  26.      */
  27.     publicstaticbyte[] encrypt(byte[] src, byte[] key) throws Exception {  
  28.         // DES演算法要求有一個可信任的隨機數源
  29.         SecureRandom sr = new SecureRandom();  
  30.         // 從原始密匙資料建立DESKeySpec物件
  31.         DESKeySpec dks = new DESKeySpec(key);  
  32.         // 建立一個密匙工廠,然後用它把DESKeySpec轉換成
  33.         // 一個SecretKey物件
  34.         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);  
  35.         SecretKey securekey = keyFactory.generateSecret(dks);  
  36.         // Cipher物件實際完成加密操作
  37.         Cipher cipher = Cipher.getInstance(DES);  
  38.         // 用密匙初始化Cipher物件
  39.         cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);  
  40.         // 現在,獲取資料並加密
  41.         // 正式執行加密操作
  42.         return cipher.doFinal(src);  
  43.     }  
  44.     /** 
  45.      * 解密 
  46.      *  
  47.      * @param src 
  48.      *            密文(位元組) 
  49.      * @param key 
  50.      *            金鑰,長度必須是8的倍數 
  51.      * @return 明文(位元組) 
  52.      * @throws Exception 
  53.      */
  54.     publicstaticbyte[] decrypt(byte[] src, byte[] key) throws Exception {  
  55.         // DES演算法要求有一個可信任的隨機數源
  56.         SecureRandom sr = new SecureRandom();  
  57.         // 從原始密匙資料建立一個DESKeySpec物件
  58.         DESKeySpec dks = new DESKeySpec(key);  
  59.         // 建立一個密匙工廠,然後用它把DESKeySpec物件轉換成
  60.         // 一個SecretKey物件
  61.         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);  
  62.         SecretKey securekey = keyFactory.generateSecret(dks);  
  63.         // Cipher物件實際完成解密操作
  64.         Cipher cipher = Cipher.getInstance(DES);  
  65.         // 用密匙初始化Cipher物件
  66.         cipher.init(Cipher.DECRYPT_MODE, securekey, sr);  
  67.         // 現在,獲取資料並解密
  68.         // 正式執行解密操作
  69.         return cipher.doFinal(src);  
  70.     }  
  71.     /** 
  72.      * 加密 
  73.      *  
  74.      * @param src 
  75.      *            明文(位元組) 
  76.      * @return 密文(位元組) 
  77.      * @throws Exception 
  78.      */
  79.     publicstaticbyte[] encrypt(byte[] src) throws Exception {  
  80.         return encrypt(src, KEY.getBytes());  
  81.     }  
  82.     /** 
  83.      * 解密 
  84.      *  
  85.      * @param src 
  86.      *            密文(位元組) 
  87.      * @return 明文(位元組) 
  88.      * @throws Exception 
  89.      */
  90.     publicstaticbyte[] decrypt(byte[] src) throws Exception {  
  91.         return decrypt(src, KEY.getBytes());  
  92.     }  
  93.     /** 
  94.      * 加密 
  95.      *  
  96.      * @param src 
  97.      *            明文(字串) 
  98.      * @return 密文(16進位制字串) 
  99.      * @throws Exception 
  100.      */
  101.     publicfinalstatic String encrypt(String src) {  
  102.         try {  
  103.             return byte2hex(encrypt(src.getBytes(), KEY.getBytes()));  
  104.         } catch (Exception e) {  
  105.             e.printStackTrace();  
  106.         }  
  107.         returnnull;  
  108.     }  
  109.     /** 
  110.      * 解密 
  111.      *  
  112.      * @param src 
  113.      *            密文(字串) 
  114.      * @return 明文(字串) 
  115.      * @throws Exception 
  116.      */
  117.     publicfinalstatic String decrypt(String src) {  
  118.         try {  
  119.             returnnew String(decrypt(hex2byte(src.getBytes()), KEY.getBytes()));  
  120.         } catch (Exception e) {  
  121.             e.printStackTrace();  
  122.         }  
  123.         returnnull;  
  124.     }  
  125.     /** 
  126.      * 加密 
  127.      *  
  128.      * @param src 
  129.      *            明文(位元組) 
  130.      * @return 密文(16進位制字串) 
  131.      * @throws Exception 
  132.      */
  133.     publicstatic String encryptToString(byte[] src) throws Exception {  
  134.         return encrypt(new String(src));  
  135.     }  
  136.     /** 
  137.      * 解密 
  138.      *  
  139.      * @param src 
  140.      *            密文(位元組) 
  141.      * @return 明文(字串) 
  142.      * @throws Exception 
  143.      */
  144.     publicstatic String decryptToString(byte[] src) throws Exception {  
  145.         return decrypt(new String(src));  
  146.     }  
  147.     publicstatic String byte2hex(byte[] b) {  
  148.         String hs = "";  
  149.         String stmp = "";  
  150.         for (int n = 0; n < b.length; n++) {  
  151.             stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));  
  152.             if (stmp.length() == 1)  
  153.                 hs = hs + "0" + stmp;  
  154.             else
  155.                 hs = hs + stmp;  
  156.         }  
  157.         return hs.toUpperCase();  
  158.     }  
  159.     publicstaticbyte[] hex2byte(byte[] b) {  
  160.         if ((b.length % 2) != 0)  
  161.             thrownew IllegalArgumentException("長度不是偶數");  
  162.         byte[] b2 = newbyte[b.length / 2];  
  163.         for (int n = 0; n < b.length; n += 2) {  
  164.             String item = new String(b, n, 2);  
  165.             b2[n / 2] = (byte) Integer.parseInt(item, 16);  
  166.         }  
  167.         return b2;  
  168.     }  
  169.     publicstaticvoid main(String[] args) {  
  170.         try {  
  171.             String src = "測試";  
  172.             String crypto = DESCipherCrossoverDelphi.encrypt(src);  
  173.             System.out.println("密文[" + src + "]:" + crypto);  
  174.             System.out.println("解密後:"
  175.                     + DESCipherCrossoverDelphi.decrypt(crypto));  
  176.         } catch (Exception e) {  
  177.             e.printStackTrace();  
  178.         }  
  179.     }  
  180. }  

    main函式執行結果如下:

Java程式碼  
  1. 密文[測試]:F25C2FB5F47CCE5F  
  2. 解密後:測試