天天看點

從零學習 CA 系列 (四) -- 常見對稱加密算法分析DES3DESAESSM43DES示例

本文參考文獻:

如有了解bug, 請大家指正。

DES

DES 算法是一個分組算法,它以64位分組對資料進行加解密。其秘鑰長度為56位,由8個位元組組成,每個位元組的第8位用作奇偶校驗。秘鑰可以是任意的56位比特塊,且可以任意時間改變,其中極少數56位比特塊被認為是弱密碼,在使用中需要避開這些弱密鑰。

從零學習 CA 系列 (四) -- 常見對稱加密算法分析DES3DESAESSM43DES示例

DES圖解

注: 外部輸入的56位密鑰(64位中去掉8個校驗位) 通過置換和位移操作生成加密和解密需要的16個48位的子密鑰。該16個子密鑰分别用于乘積變換中的16輪運算。

3DES

又稱 Triple DES, 是 DES 算法的一種變種,它使用 3 個56位的秘鑰對資料進行3次加密。3DES加解密過程如下圖:

從零學習 CA 系列 (四) -- 常見對稱加密算法分析DES3DESAESSM43DES示例

3DES加解密

K1, K2, K3 決定了 3DES 算法的安全性。若3個密鑰互不相同,則3DES算法的密鑰長度為168位,該算法又稱為 三倍長秘鑰的3DES。如 K1 = K3 ,則3DES算法的密鑰長度變為 112 位,該算法又被稱為 2 倍長密鑰的 3DES。

AES

1997年4月,美國國家标準和技術委員會 (NIST) 開始征集 “進階加密标準(AES)”算法,以便替代 DES 算法。 1998年5月,NIST 宣布接受15個新的候選算法并提請全世界密碼研究界協助分析這些候選算法,包括對每個算法的安全性和效率特性進行初步檢驗。NIST 考察了這些初步的研究結果,并標明 MARS、RC6、 Rijndael、Serpent 和 Twofish 等5個算法做為參加決賽的算法。經公衆對決賽算法進行更進一步的分析評論,2000年10月,NIST 推薦 Rijndael 作為進階加密标準(AES),并于 2001 年11月26日釋出于 FIPS PUB 197, 2002 年5月26日成為正式标準。

Rijndael 是一種疊代分組加密,采用的是代替/置換網絡(spn),它對一個 128 位的資料塊進行加密操作。加密時,首先将輸入的128位資料排成 4 x 4 的位元組矩陣,然後根據不同的秘鑰長度,進行10(128位秘鑰)、12(192位秘鑰)、14(254位秘鑰)輪的運算。其128位密鑰的加密流程如下圖:

從零學習 CA 系列 (四) -- 常見對稱加密算法分析DES3DESAESSM43DES示例

128位密鑰的加密流程

其中,每個輪函數由4層組成:

  • 第1 層非線性層,将一個 8x8 的s盒應用于每個位元組
  • 第2層(行移位變換)和第3層(列混合)是線性混合層,将 4x4 的陣列按行位移,按列混合。
  • 第4層(加密鑰變換),輪密鑰異或到陣列的每個位元組
從零學習 CA 系列 (四) -- 常見對稱加密算法分析DES3DESAESSM43DES示例

輪變換過程

SM4

SM4 算法是由中國國家密碼管理局于 2006 年 1月 6日釋出,在無線區域網路産品中準許使用的對稱密碼算法。

SM4 密碼算法是一個疊代分組密碼算法。該算法的資訊塊長度為 128 位。加密算法與密鑰擴充算法都采用 32 位非線性疊代結構。 SM4 資料解密和資料加密的算法結構相同,隻是子密碼的使用順序相反,解密子密鑰是加密子密鑰的逆序。

3DES示例

/**
     * 3DESECB加密
     * 
     * @param src
     *            要進行了加密的原文
     * @param key
     *            密鑰 key必須是長度大于等于 3*8 = 24 位
     * @return
     * @throws Exception
     */
    public static String encryptThreeDESECB(String src, String key) throws Exception {
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey securekey = keyFactory.generateSecret(dks);

        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, securekey);
        byte[] b = cipher.doFinal(src.getBytes("UTF-8"));

        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b);

    }

    /**
     * 3DESECB解密
     * 
     * @param src
     *            要解密的密文字元
     * @param key
     *            解密的Key key必須是長度大于等于 3*8 = 24 位
     * @return
     * @throws Exception
     */
    public static String decryptThreeDESECB(String src, String key) throws Exception {
        // --通過base64,将字元串轉成byte數組
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] bytesrc = decoder.decodeBuffer(src);
        // --解密的key
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey securekey = keyFactory.generateSecret(dks);

        // --Chipher對象解密
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, securekey);
        byte[] retByte = cipher.doFinal(bytesrc);

        return new String(retByte);
    }
           

繼續閱讀