Android平臺和java平臺 DES加密解密互通程序及其不能互通的原因 .

網上的demo一搜一大堆,但是,基本上都是一知半解(包括我)。爲什麼呢?我在嘗試分別在兩個平臺加密的時候,竟然發現Android DES 加密和java DES加密的程序不能互通。就是加密的結果不一樣,更不要說Android平臺的加密輸入作爲java DES的解密輸出了。這樣的話,客戶端和服務器端就不能進行通信了。我網上之前也發帖子問了不少人,但是回答都不滿意。

今天部門的另外一個同事跟我說了一下,才解決了這個不能互通的問題。

調用DES加密算法包最精要的就是下面兩句話:

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);

CBC是工作模式,DES一共有電子密碼本模式(ECB)、加密分組鏈接模式(CBC)、加密反饋模式(CFB)和輸出反饋模式(OFB)四種模式,

PKCS5Padding是填充模式,還有其它的填充模式:

然後,cipher.init()一共有三個參數:Cipher.ENCRYPT_MODE, key, zeroIv,zeroIv就是初始化向量,一個8爲字符數組。

工作模式、填充模式、初始化向量這三種因素一個都不能少。否則,如果你不指定的話,那麼就要程序就要調用默認實現。問題就來了,這就與平臺有關了。難怪網上一搜"DES加密結果不一致“,出現n多網頁結果。(之前我並沒有指定IV,被折磨了2周)

源程序如下(從java平臺到android平臺,我根本沒有更改一行代碼):

另外,一般情況下,加密後的結果都會用base64編碼進行傳輸。

java平臺:

主程序

01 public class testDES {
02  
03     /**
04      * @param args
05      * @throws Exception
06      */
07     public static void main(String[] args) throws Exception {
08         // TODO Auto-generated method stub
09         String key = "12345678";
10         String text = "12345678";
11         String result1 = DES.encryptDES(text,key);
12         String result2 = DES.decryptDES(result1, key);
13         System.out.println(result1);
14         System.out.println(result2);
15     }
16 }

用到的DES加密類
01 import javax.crypto.Cipher;
02 import javax.crypto.spec.IvParameterSpec;
03 import javax.crypto.spec.SecretKeySpec;
04  
05 public class DES {
06     private static byte[] iv = {1,2,3,4,5,6,7,8};
07     public static String encryptDES(String encryptString, String encryptKey)throws Exception {
08 //      IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
09         IvParameterSpec zeroIv = new IvParameterSpec(iv);
10         SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
11         Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
12         cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
13         byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
14       
15         return Base64.encode(encryptedData);
16     }
17     public static String decryptDES(String decryptString, String decryptKey)throws Exception {
18         byte[] byteMi = new Base64().decode(decryptString);
19         IvParameterSpec zeroIv = new IvParameterSpec(iv);
20 //      IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
21         SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES");
22         Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
23         cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
24         byte decryptedData[] = cipher.doFinal(byteMi);
25       
26         return new String(decryptedData);
27     }
28 }

用到的BASE64工具類:
001 import java.io.ByteArrayOutputStream;
002 import java.io.IOException;
003 import java.io.OutputStream;
004  
005  
006  
007 public class Base64 {
008     private static final char[] legalChars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
009     /**
010      * data[]進行編碼
011      * @param data
012      * @return
013      */
014         public static String encode(byte[] data) {
015             int start = 0;
016             int len = data.length;
017             StringBuffer buf = new StringBuffer(data.length * 3 2);
018  
019             int end = len - 3;
020             int i = start;
021             int n = 0;
022  
023             while (i <= end) {
024                 int d = ((((int) data[i]) & 0x0ff) << 16)
025                         | ((((int) data[i + 1]) & 0x0ff) << 8)
026                         | (((int) data[i + 2]) & 0x0ff);
027  
028                 buf.append(legalChars[(d >> 18) & 63]);
029                 buf.append(legalChars[(d >> 12) & 63]);
030                 buf.append(legalChars[(d >> 6) & 63]);
031                 buf.append(legalChars[d & 63]);
032  
033                 i += 3;
034  
035                 if (n++ >= 14) {
036                     n = 0;
037                     buf.append(" ");
038                 }
039             }
040  
041             if (i == start + len - 2) {
042                 int d = ((((int) data[i]) & 0x0ff) << 16)
043                         | ((((int) data[i + 1]) & 255) << 8);
044  
045                 buf.append(legalChars[(d >> 18) & 63]);
046                 buf.append(legalChars[(d >> 12) & 63]);
047                 buf.append(legalChars[(d >> 6) & 63]);
048                 buf.append("=");
049             else if (i == start + len - 1) {
050                 int d = (((int) data[i]) & 0x0ff) << 16;
051  
052                 buf.append(legalChars[(d >> 18) & 63]);
053                 buf.append(legalChars[(d >> 12) & 63]);
054                 buf.append("==");
055             }
056  
057             return buf.toString();
058         }
059  
060         private static int decode(char c) {
061             if (c >= 'A' && c <= 'Z')
062                 return ((int) c) - 65;
063             else if (c >= 'a' && c <= 'z')
064                 return ((int) c) - 97 26;
065             else if (c >= '0' && c <= '9')
066                 return ((int) c) - 48 26 26;
067             else
068                 switch (c) {
069                 case '+':
070                     return 62;
071                 case '/':
072                     return 63;
073                 case '=':
074                     return 0;
075                 default:
076                     throw new RuntimeException("unexpected code: " + c);
077                 }
078         }
079  
080         /**
081          * Decodes the given Base64 encoded String to a new byte array. The byte
082          * array holding the decoded data is returned.
083          */
084  
085         public static byte[] decode(String s) {
086  
087             ByteArrayOutputStream bos = new ByteArrayOutputStream();
088             try {
089                 decode(s, bos);
090             catch (IOException e) {
091                 throw new RuntimeException();
092             }
093             byte[] decodedBytes = bos.toByteArray();
094             try {
095                 bos.close();
096                 bos = null;
097             catch (IOException ex) {
098                 System.err.println("Error while decoding BASE64: " + ex.toString());
099             }
100             return decodedBytes;
101         }
102  
103         private static void decode(String s, OutputStream os) throws IOException {
104             int i = 0;
105  
106             int len = s.length();
107  
108             while (true) {
109                 while (i < len && s.charAt(i) <= ' ')
110                     i++;
111  
112                 if (i == len)
113                     break;
114  
115                 int tri = (decode(s.charAt(i)) << 18)
116                         + (decode(s.charAt(i + 1)) << 12)
117                         + (decode(s.charAt(i + 2)) << 6)
118                         + (decode(s.charAt(i + 3)));
119  
120                 os.write((tri >> 16) & 255);
121                 if (s.charAt(i + 2) == '=')
122                     break;
123                 os.write((tri >> 8) & 255);
124                 if (s.charAt(i + 3) == '=')
125                     break;
126                 os.write(tri & 255);
127  
128                 i += 4;
129             }
130         }
131          
132 }

adnroid平臺的主函數:
01 public class main extends Activity {
02     /** Called when the activity is first created. */
03     @Override
04     public void onCreate(Bundle savedInstanceState) {
05         super.onCreate(savedInstanceState);
06         setContentView(R.layout.main);
07         
08         String key = "12345678";
09         String text = "12345678";
10          
11          
12         try {
13             String result1 = DES.encryptDES(text,key);
14             String result2 = DES.decryptDES(result1, key);
15             Log.i("DES encode text is ", result1);
16             Log.i("DES encode text is ", result2);
17         catch (Exception e) {
18             // TODO Auto-generated catch block
19             e.printStackTrace();
20         }   
21     }
22 }

通過查看log日誌就可以看到結果。

兩個平臺的結果是一樣的,都是:

加密結果:X2p9Uo45Tzk6Ntu6W7Ev+Q==
解密結果:12345678

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章