本文參考文獻:
- 《PKI/CA 與數字證書技術大全》
- DES和AES算法詳解
如有了解bug, 請大家指正。
DES
DES 算法是一個分組算法,它以64位分組對資料進行加解密。其秘鑰長度為56位,由8個位元組組成,每個位元組的第8位用作奇偶校驗。秘鑰可以是任意的56位比特塊,且可以任意時間改變,其中極少數56位比特塊被認為是弱密碼,在使用中需要避開這些弱密鑰。

DES圖解
注: 外部輸入的56位密鑰(64位中去掉8個校驗位) 通過置換和位移操作生成加密和解密需要的16個48位的子密鑰。該16個子密鑰分别用于乘積變換中的16輪運算。
3DES
又稱 Triple DES, 是 DES 算法的一種變種,它使用 3 個56位的秘鑰對資料進行3次加密。3DES加解密過程如下圖:
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位密鑰的加密流程如下圖:
128位密鑰的加密流程
其中,每個輪函數由4層組成:
- 第1 層非線性層,将一個 8x8 的s盒應用于每個位元組
- 第2層(行移位變換)和第3層(列混合)是線性混合層,将 4x4 的陣列按行位移,按列混合。
- 第4層(加密鑰變換),輪密鑰異或到陣列的每個位元組
輪變換過程
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);
}