【Android工具類】如何保證Android與服務器的DES加密保持一致

ph44 9年前發布 | 4K 次閱讀 Java Android

轉載請注明出處: http://blog.csdn.net/zhaokaiqiang1992

    在我們的應用程序涉及到比較敏感的數據的時候,我們通常會對數據進行簡單的加密。在與服務器之間的數據交互中,除了可以使用post請求來增強數據的安全性之外,我們可以使用常見的加密算法,對數據進行加密。今天主要介紹的是DES加密算法。

    首先,DES屬于一種對稱的加密算法,所謂對稱,就是說加密和解密使用的都是同一個密鑰,那么在我們實際應用的時候,就是指服務器和客戶端進行加密解密的 時候,使用的是一個相同的密鑰。除此之外,還有非對稱加密算法,就是公鑰私鑰機制,這種方式可以被用來進行身份驗證,這個以后再細說。    

    DES全稱為Data EncryptionStandard,即數據加密標準,是一種使用密鑰加密的塊算法,DES算法的入口參數有三個:Key、Data、Mode。其中Key為7個字節共56位,是DES算法的工作密鑰;Data為8個字節64位,是要被加密或被解密的數據;Mode為DES的工作方式,有兩種:加密或解密。

    下面是在Java或者是Android里面,進行DES加密的代碼實現

    package com.qust.rollcallstudent.utils;  

    import java.security.InvalidAlgorithmParameterException;  
    import java.security.Key;  
    import java.security.spec.AlgorithmParameterSpec;  
    import java.util.Locale;  

    import javax.crypto.Cipher;  
    import javax.crypto.SecretKeyFactory;  
    import javax.crypto.spec.DESKeySpec;  
    import javax.crypto.spec.IvParameterSpec;  

    /** 
     *  
     * @ClassName: com.qust.rollcallstudent.utils.DESUtil 
     * @Description: DES加密解密工具包 
     * @author zhaokaiqiang 
     * @date 2014-11-13 下午8:40:56 
     *  
     */  
    public class DESUtil {  

        public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";  

        /** 
         * DES算法,加密 
         *  
         * @param data 
         *            待加密字符串 
         * @param key 
         *            加密私鑰,長度不能夠小于8位 
         * @return 加密后的字節數組,一般結合Base64編碼使用 
         * @throws InvalidAlgorithmParameterException 
         * @throws Exception 
         */  
        public static String encode(String key, String data) {  
            if (data == null)  
                return null;  
            try {  
                DESKeySpec dks = new DESKeySpec(key.getBytes());  
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
                // key的長度不能夠小于8位字節  
                Key secretKey = keyFactory.generateSecret(dks);  
                Cipher cipher = Cipher.getInstance(ALGORITHM_DES);  
                IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());  
                AlgorithmParameterSpec paramSpec = iv;  
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);  
                byte[] bytes = cipher.doFinal(data.getBytes());  
                return byte2String(bytes);  
            } catch (Exception e) {  
                e.printStackTrace();  
                return data;  
            }  
        }  

        /** 
         * DES算法,解密 
         *  
         * @param data 
         *            待解密字符串 
         * @param key 
         *            解密私鑰,長度不能夠小于8位 
         * @return 解密后的字節數組 
         * @throws Exception 
         *             異常 
         */  
        public static String decode(String key, String data) {  
            if (data == null)  
                return null;  
            try {  
                DESKeySpec dks = new DESKeySpec(key.getBytes());  
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
                // key的長度不能夠小于8位字節  
                Key secretKey = keyFactory.generateSecret(dks);  
                Cipher cipher = Cipher.getInstance(ALGORITHM_DES);  
                IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());  
                AlgorithmParameterSpec paramSpec = iv;  
                cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);  
                return new String(cipher.doFinal(byte2hex(data.getBytes())));  
            } catch (Exception e) {  
                e.printStackTrace();  
                return data;  
            }  
        }  

        /** 
         * 二行制轉字符串 
         *  
         * @param b 
         * @return 
         */  
        private static String byte2String(byte[] b) {  
            StringBuilder hs = new StringBuilder();  
            String stmp;  
            for (int n = 0; b != null && n < b.length; n++) {  
                stmp = Integer.toHexString(b[n] & 0XFF);  
                if (stmp.length() == 1)  
                    hs.append('0');  
                hs.append(stmp);  
            }  
            return hs.toString().toUpperCase(Locale.CHINA);  
        }  

        /** 
         * 二進制轉化成16進制 
         *  
         * @param b 
         * @return 
         */  
        private static byte[] byte2hex(byte[] b) {  
            if ((b.length % 2) != 0)  
                throw new IllegalArgumentException();  
            byte[] b2 = new byte[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;  
        }  

    }  

如果大家只是想用,就可以不用往下看了,下面開始說一些關于DES算法的細節。

    在上面的加密和解密的方法里面,我們在獲取Cipher實例的時候,傳入了一個字符串"DES/CBC/PKCS5Padding",這三個參數是什么意思呢?

    實際上,這三個參數分別對應的是“算法/模式/填充”,也就是說我們要用DES算法進行加密,采用的是CBC模式,填充方式采用PKCS5Padding。

    除了CBC模式,還有ECB模式等,指的是不同的加密方式。

    那么CBC模式和ECB模式又有什么區別呢?


    ECB模式指的是電子密碼本模式,是一種最古老,最簡單的模式,將加密的數據分成若干組,每組的大小跟加密密鑰長度相同;然后每組都用相同的密鑰加密, 比如DES算法, 如果最后一個分組長度不夠64位,要補齊64位。這種模式的特點是:

    1.每次Key、明文、密文的長度都必須是64位;

    2.數據塊重復排序不需要檢測;

    3.相同的明文塊(使用相同的密鑰)產生相同的密文塊,容易遭受字典攻擊;

    4.一個錯誤僅僅會對一個密文塊產生影響;

    

CBC模式指的是加密塊鏈模式,與ECB模式最大的不同是加入了初始向量。下面的代碼就是獲取一個初始向量,

    IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());

    這種模式的特點是:

    1.每次加密的密文長度為64位(8個字節);

    2.當相同的明文使用相同的密鑰和初始向量的時候CBC模式總是產生相同的密文;

    3.密文塊要依賴以前的操作結果,所以,密文塊不能進行重新排列;

    4.可以使用不同的初始化向量來避免相同的明文產生相同的密文,一定程度上抵抗字典攻擊;

    5.一個錯誤發生以后,當前和以后的密文都會被影響;

    

    PKCS5Padding參數則是在說明當數據位數不足的時候要采用的數據補齊方式,也可以叫做數據填充方式。

    PKCS5Padding這種填充方式,具體來說就是“填充的數字代表所填字節的總數”

    比如說,差兩個字節,就是######22,差5個字節就是###55555,這樣根據最后一個自己就可以知道填充的數字和數量。

   

    介紹完DES的這些細節之后,我們就可以知道,在不同的平臺上,只要能保證這幾個參數的一致,就可以實現加密和解密的一致性。

    1.加密和解密的密鑰一致

    2.采用CBC模式的時候,要保證初始向量一致

    3.采用相同的填充模式

 本文由用戶 ph44 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!