DES的加密和解密
一提到對稱加密,大家首先想到的可能就是DES(Data Encryption Standard)技術(shù)了.DES技術(shù)是一種將64比特的明文加密成64比特的密文的對稱密碼算法,因此理論上來講,他的密鑰長度也是64位,但因?yàn)樵贒ES的密鑰中每隔7比特,就會設(shè)置一個(gè)用于錯(cuò)誤檢查的比特,所以實(shí)際上DES的密鑰的長度只有56比特.
DES是以64比特的明文(比特序列)為一個(gè)單位進(jìn)行加密,這64比特的單位成為分組,一般來說,以分組為單位進(jìn)行處理的密碼算法成為分組密碼.因此它只能加密64比特的數(shù)據(jù),對于長度超過64比特的明文,就需要對DES加密進(jìn)行迭代.DES加密和解密的過程如下圖所示:

DES的結(jié)構(gòu)(Feistel網(wǎng)絡(luò))
因?yàn)镈ES的基本結(jié)構(gòu)是由Horst Feistel設(shè)計(jì)的,所以DES的基本結(jié)構(gòu)也被稱為Feistel網(wǎng)絡(luò).在Feistel網(wǎng)絡(luò)中,加密的各個(gè)步驟稱為輪,整個(gè)加密過程就是進(jìn)行若干次輪的循環(huán).DES就是一種16輪循環(huán)的Feistel網(wǎng)絡(luò).

上面的圖表示出了Feistel網(wǎng)絡(luò)中一輪的計(jì)算流程.通過上面的圖我們可以知道,在這一過程中起到關(guān)鍵作用的就是輪函數(shù):他根據(jù)歐策和子密鑰生成對”左側(cè)”進(jìn)行加密的比特序列.然后輪函數(shù)的輸出與左側(cè)進(jìn)行XOR運(yùn)算,得到了左側(cè)的加密結(jié)果,過程梳理如下:
- 輸入的數(shù)據(jù)被分為左右兩部分
- 輸入的右側(cè)直接發(fā)送到輸出的右側(cè)
- 輸入的右側(cè)發(fā)送到輪函數(shù)
- 輪函數(shù)根據(jù)右側(cè)數(shù)據(jù)和子密鑰,計(jì)算出比特序列
- 左側(cè)數(shù)據(jù)與輪函數(shù)的輸出進(jìn)行XOR運(yùn)算,得到輸出的加密后的左側(cè).
但是,我們根據(jù)圖也能發(fā)現(xiàn),這樣雖然左側(cè)經(jīng)過加密了,但右側(cè)并沒有經(jīng)過加密.所以Feistel網(wǎng)絡(luò)需要進(jìn)行第二次的輪加密,并且需要將左側(cè)和右側(cè)進(jìn)行對調(diào).一般來說DES加密是需要三次輪加密的,并且這一過程是可逆的,只要子密鑰不變,就能夠從密文推導(dǎo)出明文.這也就是Feistel網(wǎng)絡(luò)的解密操作原理.我們現(xiàn)在來總結(jié)一下Feistel網(wǎng)絡(luò)的一些性質(zhì): - 經(jīng)過我們之上的說明,很容易就知道Feistel網(wǎng)絡(luò)的輪數(shù)是可以任意增加的.并且無論有多少輪,都是可以解密的.
- 加密時(shí)無論使用任何函數(shù)作為輪函數(shù),都可以正確解密
- 加密和解密可以用完全相同的結(jié)構(gòu)來實(shí)現(xiàn).
現(xiàn)在我們附上一段DES加密算法在Java中的實(shí)現(xiàn):
package org.shangzeng.cipher;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
public class DESTest {
public static void main(String[] args) {
String greeting="HelloWorld";
String key="shangzeng";
try {
byte[] encryptArray=DESTest.encryptDES(greeting.getBytes(),key.getBytes());
System.out.println(greeting+"加密后的結(jié)果為:"+new String(encryptArray));
byte[] decryptArray=DESTest.decryptDES(encryptArray,key.getBytes());
System.out.println(greeting+"解密后的結(jié)果為:"+new String(decryptArray));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
//DES算法要有一個(gè)隨機(jī)數(shù)源,因?yàn)镽andom是根據(jù)時(shí)間戳生成的有限隨機(jī)數(shù),比較容易破解,所以在這里使用SecureRandom
private static SecureRandom secureRandom=new SecureRandom();
private static SecretKey getSecretKey(byte[] keyArray) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
DESKeySpec desKeySpec=new DESKeySpec(keyArray);
//創(chuàng)建DES密鑰工廠
SecretKeyFactory keyFactory=SecretKeyFactory.getInstance("DES");
//用密鑰工廠將DESKeySpec轉(zhuǎn)換成密鑰key
SecretKey secretKey=keyFactory.generateSecret(desKeySpec);
return secretKey;
}
public static byte[] encryptDES(byte[] contentArray,byte[] keyArray) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
return des(contentArray,keyArray,Cipher.ENCRYPT_MODE);
}
public static byte[] decryptDES(byte[] encryptArray,byte[] keyArray) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidKeySpecException {
return des(encryptArray,keyArray,Cipher.DECRYPT_MODE);
}
private static byte[] des(byte[] contentArray,byte[] keyArray,int mode) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException {
SecretKey secretKey=getSecretKey(keyArray);
//獲取真正執(zhí)行加/解密操作的Cipher
Cipher cipher=Cipher.getInstance("DES");
//執(zhí)行加/解密操作
cipher.init(mode,secretKey,secureRandom);
byte[] result=cipher.doFinal(contentArray);
return result;
}
}
講到這里,必須要提一下,差分分析和線性分析.
差分分析是一種針對分組密碼的分析方法,他的思路是”改變一部分明文并分析密文如何隨之改變”.理論上來說,明文只要改變,哪怕是一個(gè)比特的改變,密文的比特排列也應(yīng)該徹底的改變.因此只要通過分析密文改變中所產(chǎn)生的偏差,就可以獲得破譯密碼的線索.
線性分析是由松井充提出的,他的思路是:”將明文和密文的一些對應(yīng)比特進(jìn)行XOR并計(jì)算其結(jié)果為零的概率”,如果密文具備足夠的隨機(jī)性,則任選一些明文和密文的對應(yīng)比特進(jìn)行XOR結(jié)果為零的概率為1/2.如果能夠找到大幅偏離1/2的部分,則可以借此獲得一些與密鑰有關(guān)的信息.如果使用線性分析,對于DES只需要247組明文和密文就能夠完成破解.相比需要嘗試256個(gè)密鑰的暴力破解來說,所需的計(jì)算量大幅減少.
密碼破譯者可以選擇任意明文并獲得其加密的結(jié)果,這是差分分析和線性分析的一個(gè)大前提.這種攻擊方式也被稱為 選擇明文攻擊(CPA,Chosen Plaintext Attack)
DES從1977年開始被美國聯(lián)邦信息處理標(biāo)準(zhǔn)(FIPS)采用,主要被用于國家政府和銀行等行業(yè),但在1999年1月,distributed.net與電子前哨基金會合作,在22小時(shí)15分鐘內(nèi)即公開破解了一個(gè)DES密鑰,另有一些分析報(bào)告提出了該算法的理論上的弱點(diǎn)。在2001年,DES作為一個(gè)標(biāo)準(zhǔn)已經(jīng)被所取代。另外,DES已經(jīng)不再作為美國國家標(biāo)準(zhǔn)科技協(xié)會(前國家標(biāo)準(zhǔn)局)的一個(gè)標(biāo)準(zhǔn).
如果說DES不安全,那么我們該用什么加密算法呢?期待下次分享
《詳細(xì)解析DES系列加密技術(shù)(二)》
如果大家有什么建議或問題,歡迎大家進(jìn)群討論,另群里有學(xué)習(xí)資料奉送哦
群號為: 661594029