Java與Delphi交叉DES加解密的問題
阿新 • • 發佈:2019-02-16
何為交叉加解密?
——Java加密、Delphi解密,或 Delphi加密、Java解密。
近日,手頭上當前的專案進展到優化、完善階段,其中一點是需要增強服務端與客戶端通訊的安全性,考慮採用對報文進行DES加密的方法來實現。
服務端是Java編寫的,客戶端是Delphi編寫的,原以為兩端各自coding完進行個聯調就OK了,結果發現同樣的明文、金鑰通過Delphi、Java所產生的密文是不同的。
在網上搜索相關資源,得出結論:
原來這是個普遍存在的問題,主要原因是不同的語言在明文的長度不夠8byte倍數時,補充的位元組各不相同所致。
Java和C之間已經有解決方案(http://shirlly.iteye.com/blog/310759
- import java.security.SecureRandom;
- import javax.crypto.Cipher;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.DESKeySpec;
- /**
- * DES加解密,支援與delphi互動(字串編碼需統一為UTF-8)
- *
- * @author wym
- */
- publicclass
- /**
- * 金鑰
- */
- publicstaticfinal String KEY = "12345678";
- privatefinalstatic String DES = "DES";
- /**
- * 加密
- *
- * @param src
- * 明文(位元組)
- * @param key
- * 金鑰,長度必須是8的倍數
- * @return 密文(位元組)
- * @throws Exception
- */
- publicstaticbyte[] encrypt(byte[] src, byte[] key) throws Exception {
- // DES演算法要求有一個可信任的隨機數源
- SecureRandom sr = new SecureRandom();
- // 從原始密匙資料建立DESKeySpec物件
- DESKeySpec dks = new DESKeySpec(key);
- // 建立一個密匙工廠,然後用它把DESKeySpec轉換成
- // 一個SecretKey物件
- SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
- SecretKey securekey = keyFactory.generateSecret(dks);
- // Cipher物件實際完成加密操作
- Cipher cipher = Cipher.getInstance(DES);
- // 用密匙初始化Cipher物件
- cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
- // 現在,獲取資料並加密
- // 正式執行加密操作
- return cipher.doFinal(src);
- }
- /**
- * 解密
- *
- * @param src
- * 密文(位元組)
- * @param key
- * 金鑰,長度必須是8的倍數
- * @return 明文(位元組)
- * @throws Exception
- */
- publicstaticbyte[] decrypt(byte[] src, byte[] key) throws Exception {
- // DES演算法要求有一個可信任的隨機數源
- SecureRandom sr = new SecureRandom();
- // 從原始密匙資料建立一個DESKeySpec物件
- DESKeySpec dks = new DESKeySpec(key);
- // 建立一個密匙工廠,然後用它把DESKeySpec物件轉換成
- // 一個SecretKey物件
- SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
- SecretKey securekey = keyFactory.generateSecret(dks);
- // Cipher物件實際完成解密操作
- Cipher cipher = Cipher.getInstance(DES);
- // 用密匙初始化Cipher物件
- cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
- // 現在,獲取資料並解密
- // 正式執行解密操作
- return cipher.doFinal(src);
- }
- /**
- * 加密
- *
- * @param src
- * 明文(位元組)
- * @return 密文(位元組)
- * @throws Exception
- */
- publicstaticbyte[] encrypt(byte[] src) throws Exception {
- return encrypt(src, KEY.getBytes());
- }
- /**
- * 解密
- *
- * @param src
- * 密文(位元組)
- * @return 明文(位元組)
- * @throws Exception
- */
- publicstaticbyte[] decrypt(byte[] src) throws Exception {
- return decrypt(src, KEY.getBytes());
- }
- /**
- * 加密
- *
- * @param src
- * 明文(字串)
- * @return 密文(16進位制字串)
- * @throws Exception
- */
- publicfinalstatic String encrypt(String src) {
- try {
- return byte2hex(encrypt(src.getBytes(), KEY.getBytes()));
- } catch (Exception e) {
- e.printStackTrace();
- }
- returnnull;
- }
- /**
- * 解密
- *
- * @param src
- * 密文(字串)
- * @return 明文(字串)
- * @throws Exception
- */
- publicfinalstatic String decrypt(String src) {
- try {
- returnnew String(decrypt(hex2byte(src.getBytes()), KEY.getBytes()));
- } catch (Exception e) {
- e.printStackTrace();
- }
- returnnull;
- }
- /**
- * 加密
- *
- * @param src
- * 明文(位元組)
- * @return 密文(16進位制字串)
- * @throws Exception
- */
- publicstatic String encryptToString(byte[] src) throws Exception {
- return encrypt(new String(src));
- }
- /**
- * 解密
- *
- * @param src
- * 密文(位元組)
- * @return 明文(字串)
- * @throws Exception
- */
- publicstatic String decryptToString(byte[] src) throws Exception {
- return decrypt(new String(src));
- }
- publicstatic String byte2hex(byte[] b) {
- String hs = "";
- String stmp = "";
- for (int n = 0; n < b.length; n++) {
- stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
- if (stmp.length() == 1)
- hs = hs + "0" + stmp;
- else
- hs = hs + stmp;
- }
- return hs.toUpperCase();
- }
- publicstaticbyte[] hex2byte(byte[] b) {
- if ((b.length % 2) != 0)
- thrownew IllegalArgumentException("長度不是偶數");
- byte[] b2 = newbyte[b.length / 2];
- for (int n = 0; n < b.length; n += 2) {
- String item = new String(b, n, 2);
- b2[n / 2] = (byte) Integer.parseInt(item, 16);
- }
- return b2;
- }
- publicstaticvoid main(String[] args) {
- try {
- String src = "測試";
- String crypto = DESCipherCrossoverDelphi.encrypt(src);
- System.out.println("密文[" + src + "]:" + crypto);
- System.out.println("解密後:"
- + DESCipherCrossoverDelphi.decrypt(crypto));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
main函式執行結果如下:
Java程式碼- 密文[測試]:F25C2FB5F47CCE5F
- 解密後:測試