3DES加密算法原理

 

一、3DES加密算法簡析:

3DES,也稱爲 3DESede 或 TripleDES,是三重數據加密算法,相當於是對每個數據庫應用三次DES的對稱加密算法。

由於DES密碼長度容易被暴力破解,所以3DES算法通過對DES算法進行改進,增加DES的密鑰長度來避免類似的攻擊,針對每個數據塊進行三次DES加密;因此,3DES加密算法並非什麼新的加密算法,是DES的一個更安全的變形,它以DES爲基本模塊,通過組合分組方法設計出分組加密算法。。

3DES是DES向AES過渡的加密算法,它使用2個或者3個56位的密鑰對數據進行三次加密。相比DES,3DES因密鑰長度變長,安全性有所提高,但其處理速度不高。因此又出現了AES加密算法,AES較於3DES速度更快、安全性更高。

 

二、3DES加密過程:

該算法的加解密過程分別是對明文/密文數據進行三次DES加密或解密,得到相應的密文或明文。

假設EK()和DK()分別表示DES的加密和解密函數,P表示明文,C表示密文,那麼加解密的公式如下:

加密:C = EK3( DK2( EK1(P)) ),即對明文數據進行,加密 --> 解密 --> 加密的過程,最後得到密文數據;

解密:P = DK1( EK2( DK3(C)) ),即對密文數據進行,解密 --> 加密 --> 解密的過程,最後得到明文數據;

其中:K1表示3DES中第一個8字節密鑰,K2表示第二個8字節密鑰,K3表示第三個8字節密鑰,K1、K2、K3決定了算法的安全性,若三個密鑰互不相同,本質上就相當於用一個長爲168位的密鑰進行加密。多年來,它在對付強力攻擊時是比較安全的。若數據對安全性要求不那麼高,K1可以等於K3。在這種情況下,密鑰的有效長度爲112位,即K1對應KL(左8字節),K2對應KR(右8字節),K3對應KL(左8字節)。

當三重密鑰均相同時,前兩步相互抵消,相當於僅實現了一次加密,因此可實現對普通DES加密算法的兼容。

由於DES加解密算法是每8個字節作爲一個加解密數據塊,因此在實現該算法時,需要對數據進行分塊和補位(即最後不足8字節時,要補足8字節)。Java本身提供的API中NoPadding,Zeros填充和PKCS5Padding。假設我們要對9個字節長度的數據進行加密,則其對應的填充說明如下:

(1)NoPadding:API或算法本身不對數據進行處理,加密數據由加密雙方約定填補算法。例如若對字符串數據進行加解密,可以補充\0或者空格,然後trim;

(2)ZerosPadding:無數據的字節全部被填充爲0;

第一塊:F0 F1 F2 F3 F4 F5 F6 F7

第二塊:F8 0 0 0 0 0 0 0

(3)PKCS5Padding:每個被填充的字節都記錄了被填充的長度;

①加密前:數據字節長度對8取餘,餘數爲m,若m>0,則補足8-m個字節,字節數值爲8-m,即差幾個字節就補幾個字節,字節數值即爲補充的字節數,若爲0則補充8個字節的8。

②解密後:取最後一個字節,值爲m,則從數據尾部刪除m個字節,剩餘數據即爲加密前的原文。

③加密字符串爲爲AAA,則補位爲AAA55555;加密字符串爲BBBBBB,則補位爲BBBBBB22;加密字符串爲CCCCCCCC,則補位爲CCCCCCCC88888888。

(4)PKCS7Padding:

PKCS7Padding 的填充方式和PKCS5Padding 填充方式一樣。只是加密塊的字節數不同。PKCS5Padding明確定義了加密塊是8字節,PKCS7Padding加密快可以是1-255之間。

 

三、3DES解密:

3DES解密過程,與加密過程相反,即逆序使用密鑰。是以密鑰3、密鑰2、密鑰1的順序執行 解密->加密->解密

 

 

四、Java使用3DES加密解密的流程:

3des加密解密詳細解釋

  ①傳入共同約定的密鑰(keyBytes)以及算法(Algorithm),來構建SecretKey密鑰對象:

  SecretKey deskey = new SecretKeySpec(keyBytes, Algorithm);

  ②根據算法實例化Cipher對象,它負責加密/解密:

  Cipher c1 = Cipher.getInstance(Algorithm);

  ③傳入加密/解密模式以及SecretKey密鑰對象,實例化Cipher對象:

  c1.init(Cipher.ENCRYPT_MODE, deskey);

  ④傳入字節數組,調用Cipher.doFinal()方法,實現加密/解密,並返回一個byte字節數組:

  c1.doFinal(src);

Java語言加密案例:

/*字符串 DESede(3DES) 加密*/
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
 
public class Des3 {
 
    private static final String Algorithm = "DESede"; // 定義 加密算法,可用DES,DESede,Blowfish

    // 加密函數
    // keybyte爲加密密鑰,長度爲24字節
    // src爲被加密的數據緩衝區(源)
    public static byte[] encryptMode(byte[] keybyte, byte[] src) {
        try {
            // 生成密鑰
            SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
            // 加密
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            return c1.doFinal(src);
        } catch (java.security.NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (javax.crypto.NoSuchPaddingException e2) {
            e2.printStackTrace();
        } catch (java.lang.Exception e3) {
            e3.printStackTrace();
        }
        return null;
    }
 
    // 解密函數
    // keybyte爲加密密鑰,長度爲24字節
    // src爲加密後的緩衝區
    public static byte[] decryptMode(byte[] keybyte, byte[] src) {
        try {
            // 生成密鑰
            SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
            // 解密
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.DECRYPT_MODE, deskey);
            return c1.doFinal(src);
        } catch (java.security.NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (javax.crypto.NoSuchPaddingException e2) {
            e2.printStackTrace();
        } catch (java.lang.Exception e3) {
            e3.printStackTrace();
        }
        return null;
    }
 
    // 轉換成十六進制字符串
    public static 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;
            }
            if (n < b.length - 1) {
                hs = hs + ":";
            }
        }
        return hs.toUpperCase();
    }
 
    public static void main(String[] args) {
 
        // 添加新安全算法,如果用JCE就要把它添加進去
        Security.addProvider(new com.sun.crypto.provider.SunJCE());
        final byte[] keyBytes = { 0x11, 0x22, 0x4F, 0x58, (byte) 0x88, 0x10, 0x40, 0x38, 0x28, 0x25, 0x79, 0x51, (byte) 0xCB, (byte) 0xDD, 0x55, 0x66, 0x77, 0x29, 0x74, (byte) 0x98, 0x30, 0x40, 0x36, (byte) 0xE2 }; // 24字節的密鑰
 
        String szSrc = "This is a 3DES test. 測試";
        System.out.println("加密前的字符串:" + szSrc);
 
        byte[] encoded = encryptMode(keyBytes, szSrc.getBytes());
        System.out.println("加密後的字符串:" + new String(encoded));
 
        byte[] srcBytes = decryptMode(keyBytes, encoded);
        System.out.println("解密後的字符串:" + (new String(srcBytes)));
    }
}

 

 

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