Java和Objective-C中字元編碼及DES加密解密

來源:互聯網
上載者:User
1.概述

在基於互連網的應用中,發送端將字元採用某種方式加密後傳輸;而接受端根據事先約定的密鑰進行解密,這樣即使傳輸的字元被截獲,也不會輕易被識別。而且,現在很多應用環境都很複雜,服務端是JAVA應用,用戶端有JAVA應用、智能手機應用。我們以服務端為JAVA應用,用戶端為智能手機IOS應用為例,實現在服務端加密一段字元,傳輸到用戶端解密;在用戶端又加密一段字元,傳輸到服務端解密,這樣一個較為複雜的過程。

對於這種需求,有很多實現方式,如採用https加安全數位憑證來實現,它在金融行業用得比較多。

這裡採用DES演算法完成這種字元安全傳輸的需求。首先聲明一下,DES演算法我也瞭解不多,下面的論述肯定有遺漏、錯誤等等不足之處,請參考性閱讀,發現錯誤等請告訴我。在此先行謝過。

2.Java字元編碼

所有電腦的字元都是按照某種字元集進行編碼的,在網路中真正傳輸的是位元組。

在用戶端發送某串字元如”miki西遊:mikixiyou@126.com”,它會按照用戶端的字元集進行編碼,形成位元組流,在傳輸到某個服務端前,還需要使用BASE64進行編碼,然後傳到服務端。

服務端接收到之後,使用BASE64進行解碼,然後按照它的預設字元集進行解碼,形成字串。如果用戶端和服務端使用的預設字元集是一致的,如都是GBK,那麼就會正確顯示這段字元文字。如果不正確,如用戶端用GBK編碼,而伺服器端用UTF8編碼,那麼就會出現亂碼。我們經常在瀏覽器上見到亂碼啊問號號等字元,就是這樣字元集不一致所導致的。

   public static void main(String args[]) throws Exception {

 

       String source = "miki西遊| mikixiyou@126.com";

      

       StringcharsetName=System.getProperty("file.encoding");

       System.out.println("file.encodingis "+charsetName);

       System.out.println("source="+source);

       System.out.println(parseByte2HexStr(source.getBytes("GBK")));

       System.out.println(parseByte2HexStr(source.getBytes()));

              

       System.out.println(parseByte2HexStr(source.getBytes("UTF-8")));

       String source_utf8=newString (source.getBytes("UTF-8"),"UTF-8");

       System.out.println("source_utf8="+source_utf8);

       String source_gbk=newString (source.getBytes("GBK"),"GBK");       

       System.out.println("source_gbk="+source_gbk);

   }

一般我們使用這個方法source.getBytes()的source字串預設字元集的編碼。

String source = "西遊abc@126.com";

System.out.println(parseByte2HexStr(source.getBytes()));

輸出結果為

CEF7D3CE616263403132362E636F6D

前兩個位元組CEF7表示“西”,後兩個位元組D3CE表示“遊”。GBK字元集對於漢字採用兩位元組編碼的。

字串source的預設字元集可以通過系統屬性得到,它是每一個JAVA的檔案編碼。擷取的方法如下:

       StringcharsetName=System.getProperty("file.encoding");

       System.out.println("file.encodingis "+charsetName);

輸出結果為

file.encoding is GBK

 

如果按照UTF-8字元集擷取編碼,那麼輸出的位元組流將按照UTF-8編碼方式進行輸出。

       System.out.println(parseByte2HexStr(source.getBytes("UTF-8")));

       String source_utf8=newString (source.getBytes("UTF-8"),"UTF-8");

輸出結果為

E8A5BFE6B8B8616263403132362E636F6D

前三個位元組E8A5BF表示“西”,後三個位元組E6B8B8表示“遊”。UTF-8字元集對於漢字採用三位元組編碼的。

在互連網中,傳輸的位元組流還需要進行BASE64編碼。我不知道是不是因為位元組流太長了什麼的,需要BASE64編碼壓縮一下,還是其他什麼目的。

BASE64的使用很簡單,網上原始碼很多。基本是使用這兩個方法,“String encode(byte[] data)“將位元組數組編碼成字串,“byte[]decode(String s)”將字串還原成位元組數組。

3.Java位元組加密

在JAVA類中匯入 javax.crypto.Cipher;包,使用Cipher.getInstance("DES/CBC/PKCS5Padding");方法實現加密。

注意,這裡使用PKCS5Padding演算法,密鑰只能是8個位元組。

因為在ios中,支援的DES密碼編譯演算法是kCCOptionPKCS7Padding |kCCOptionECBMode。在使用PKCS7Padding,它的密鑰可以是8個位元組,也可以不是。如果密鑰不是8個位元組的話,那麼JAVA端的PKCS5Padding演算法就不能解密了。

我對DES演算法也瞭解甚少,這裡只說一下自己的理解。在密鑰都是8個位元組的前提下,PKCS7Padding和PKCS5Padding的加密和解密是通用的。因此,不必糾結於兩個演算法不一樣怎麼辦,如何讓IOS也支援JAVA的密碼編譯演算法,甚至不用DES了等等。

我覺得都沒必要,我們做的是工程,一種需求的實現方法。只要遵守密鑰為8個位元組的約定,就能實現需求,又何必去找其他的演算法。好吧,我理解你覺得這樣不安全,其實也沒絕對的安全。

回到正題,JAVA中DES加密實現方法如下:

private static byte[] iv = {1, 2, 3, 4, 5, 6, 7, 8};

 

   public static byte[]encryptDES(String encryptString, String encryptKey)

           throws Exception {

 

       System.out.println("willencryptedData with UTF-8 encoding =" + parseByte2HexStr(encryptString.getBytes("UTF-8")));

      

       IvParameterSpec zeroIv =new IvParameterSpec(iv);

       SecretKeySpec key = newSecretKeySpec(encryptKey.getBytes(), "DES");

       Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

       cipher.init(Cipher.ENCRYPT_MODE,key, zeroIv);

       byte[] encryptedData =cipher.doFinal(encryptString.getBytes("UTF-8"));

       System.out.println("didencryptedData  =" + parseByte2HexStr(encryptedData));

       return encryptedData;

   }

 

   public static StringencryptDESwithBase64(String encryptString,String encryptKey) throws Exception

   {

       return XYBase64.encode(encryptDES(encryptString,encryptKey));

   }

JAVA中DES解密實現方法如下:

   public static String decryptDES(byte[] encryptedData, StringdecryptKey)

           throws Exception {

       System.out.println("willdecryptedData =" + parseByte2HexStr(encryptedData));

      

       IvParameterSpec zeroIv =new IvParameterSpec(iv);

       SecretKeySpec key = newSecretKeySpec(decryptKey.getBytes("UTF-8"), "DES");

       Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

       cipher.init(Cipher.DECRYPT_MODE,key, zeroIv);

       byte decryptedData[] =cipher.doFinal(encryptedData);

 

       System.out.println("diddecryptedData with UTF-8 encoding =" + parseByte2HexStr(decryptedData));

 

       String decryptedString =new String(decryptedData, "UTF-8");

       System.out.println("diddecryptedString with UTF-8 encoding =" + decryptedString);

       return decryptedString;

   }

   public static StringdecryptDESwithBase64(String encryptedString, String decryptKey)  throws Exception

   {

       byte[]encryptedData=XYBase64.decode(encryptedString);

       return decryptDES(encryptedData,decryptKey);      

   }  

在main()中調試一下,結果符合預期。

   public static void main(String[] args) throws Exception {

       String plainText = "abcdefghihjjjkelaemn";

       String keyText = "20120401";

 

       plainText = "miki西遊| mikixiyou@126.com";

       keyText = "abcd1234";

 

       byte[] encryptedData = encryptDES(plainText,keyText);

       String decryptedString=decryptDES(encryptedData,keyText);

      

       String cipherText = parseByte2HexStr(encryptedData);

      

       System.out.println("明文:" + plainText);

       System.out.println("密鑰:" + keyText);

       System.out.println("密文 Base 64 編碼:" + cipherText);

       System.out.println("解密後:" + decryptedString);    

      

       String encryptedString =encryptDESwithBase64(plainText, keyText);

       decryptedString=decryptDESwithBase64(encryptedString,keyText);

      

       System.out.println("明文:" + plainText);

       System.out.println("密鑰:" + keyText);

       System.out.println("密文:" + encryptedString);

       System.out.println("解密後:" + decryptedString);

   }

輸出結果如下:

will encryptedData with UTF-8 encoding=E8A5BFE6B8B8616263403132362E636F6D

did encryptedData =A69C602B3F74BD6273DE730D6214026B8FE538E4AB9F8547

will decryptedData =A69C602B3F74BD6273DE730D6214026B8FE538E4AB9F8547

did decryptedData with UTF-8 encoding =E8A5BFE6B8B8616263403132362E636F6D

did decryptedString with UTF-8 encoding =miki西遊| mikixiyou@126.com

明文:miki西遊| mikixiyou@126.com

密鑰:abcd1234

密文 Base 64 編碼:A69C602B3F74BD6273DE730D6214026B8FE538E4AB9F8547

解密後:miki西遊| mikixiyou@126.com

will encryptedData with UTF-8 encoding =E8A5BFE6B8B8616263403132362E636F6D

did encryptedData =A69C602B3F74BD6273DE730D6214026B8FE538E4AB9F8547

will decryptedData =A69C602B3F74BD6273DE730D6214026B8FE538E4AB9F8547

did decryptedData with UTF-8 encoding=E8A5BFE6B8B8616263403132362E636F6D

did decryptedString with UTF-8 encoding =miki西遊| mikixiyou@126.com

明文:miki西遊| mikixiyou@126.com

密鑰:abcd1234

密文:ppxgKz90vWJz3nMNYhQCa4/lOOSrn4VH

解密後:miki西遊| mikixiyou@126.com

這樣,我們就實現了JAVA中的加密和解密。但要在用戶端也實現這樣的加密和解密演算法才算最終完成任務。

4.Objective-C字元編碼

 

 待續

5.Objective-C位元組加密

 

 

  待續

 

 

6.參考資料

http://www.cnblogs.com/midea0978/articles/1437257.html

http://www.cnblogs.com/silentjesse/archive/2011/11/04/2235674.html

關於Objective-c和Java下DES加密保持一致的方式。這個文檔我找不到原始作者,只看到很多轉載,所以不寫超連結了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.