資料加密標準(DES)詳解
阿新 • • 發佈:2020-03-09
# 1 簡介
## 1.1 歷史
DES(Data Encryption Standard)是由IBM公司在**1974年提出**的加密演算法,在**1977年被NIST定位資料加密標準**。隨後的很多年裡,DES都是最流行的對稱密碼演算法,尤其是在金融領域更是如此,直到90年代隨著對DES研究的深入和算力的發展,DES變得不再那麼安全,但1994年NIST仍然公佈了DES在未來地5年將繼續作為資料加密標準,到1999年,NIST宣佈DES將只在法律系統中使用並推出了它的改進版3DES,即使用兩個或三個不同的金鑰重複三次DES的操作。直到**2001年,AES(Adanced Encryption Standard)的提出,DES逐漸退出了歷史舞臺**。
這裡簡單提一句,DES的不安全性主要源自於它的**金鑰過短**,只有64位,所以其改進版3DES到今天依然活躍在很多加密系統中。
## 1.2 結構
DES使用了典型的Feistel結構(見[維基百科]([https://zh.wikipedia.org/zh-hans/%E8%B4%B9%E6%96%AF%E5%A6%A5%E5%AF%86%E7%A0%81](https://zh.wikipedia.org/zh-hans/費斯妥密碼))),只在開始時添加了一個初始置換和結束時添加了一個逆初始置換。
結構圖表示如下:
![](https://img2020.cnblogs.com/blog/1760780/202003/1760780-20200308215007324-342624211.png)
首先解釋一下上圖,DES共有16輪,對於每個輸入的分組(64bit),首先會進行一次初始置換($IP$),初始置換後即進行16輪的加密,種子金鑰會為每一輪加密操作生成一個48bit的輪金鑰,具體的生成過程以及為什麼是48bit後邊會有相應的解釋。
對每一輪來說,輸入的資料都被分為左右兩部分,各32bit。每一輪的右半部分成為下一輪的左半部分,而左半部分同經過一系列操作的右半部分異或成為新的右半部分(除16輪)。
16輪加密結束後,會首先進行一次左右部分的互換,再進行一次逆初始置換($IP^{-1}$)就得到了64bit的密文分組,下面我們來詳細介紹每一輪操作具體發生了什麼,以及輪金鑰是如何生成的。
# 2 演算法描述
## 2.1 $IP,IP^{-1}$
講內部結構之前先介紹一下初始置換和逆初始置換的具體操作:
其實都是很簡單的根據表換位置的操作,首先是初始置換:
| 58 | 50 | 42 | 34 | 26 | 18 | 10 | 2 |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 60 | 52 | 44 | 36 | 28 | 20 | 12 | 4 |
| 62 | 54 | 46 | 38 | 30 | 22 | 14 | 6 |
| 64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
| 57 | 49 | 41 | 33 | 25 | 17 | 9 | 1 |
| 59 | 51 | 43 | 35 | 27 | 19 | 11 | 3 |
| 61 | 53 | 45 | 37 | 29 | 21 | 13 | 5 |
| 63 | 55 | 47 | 39 | 31 | 23 | 15 | 7 |
即將輸入明文的第58位放到第一位,第50位放到第二位,以此類推,
相應的,逆初始置換就是把要輸出的密文按照表進行置換(我想設定它的原因應該是為了對稱地解密):
| 40 | 8 | 48 | 16 | 56 | 24 | 64 | 32 |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 39 | 7 | 47 | 15 | 55 | 23 | 63 | 31 |
| 38 | 6 | 46 | 14 | 54 | 22 | 62 | 30 |
| 37 | 5 | 45 | 13 | 53 | 21 | 61 | 29 |
| 36 | 4 | 44 | 12 | 52 | 20 | 60 | 28 |
| 35 | 3 | 43 | 11 | 51 | 19 | 59 | 27 |
| 34 | 2 | 42 | 10 | 50 | 18 | 58 | 26 |
| 33 | 1 | 41 | 9 | 49 | 17 | 57 | 25 |
## 2.2 輪加密
對每輪操作來說,都是隻需要對輸入資料的右半部分的32bit進行操作。每輪加密的內部結構可以用下圖來表示:
![img](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/DES-f-function.png/250px-DES-f-function.png)
- **擴張**:將32bit的右半部分拓張為48bit的值,從下表可以看出,實際上就是以4bit為一組,把原本左右相鄰的bit複製一次,擴張為6*8=48bit
| 32 | 1 | 2 | 3 | 4 | 5 |
| :--: | :--: | :--: | :--: | :--: | :--: |
| 4 | 5 | 6 | 7 | 8 | 9 |
| 8 | 9 | 10 | 11 | 12 | 13 |
| 12 | 13 | 14 | 15 | 16 | 17 |
| 16 | 17 | 18 | 19 | 20 | 21 |
| 20 | 21 | 22 | 23 | 24 | 25 |
| 24 | 25 | 26 | 27 | 28 | 29 |
| 28 | 29 | 30 | 31 | 32 | 1 |
- **輪金鑰加**:將拓展置換生成的48bit與輪金鑰異或,輪金鑰同樣是48bit的,輪金鑰如何生成將在下一部分解釋
- **S盒替換**:S盒是DES中最核心的部分,有了S盒DES才具有了非線性的性質,安全性得到保障。S盒將輸入的48bit轉化位32bit的輸出,它的實現細節可以簡述為:S盒共8個,每個S盒可以看作一個4*16的矩陣,將輸入每6bit一組輸入對應的S盒,輸入的第0、5bit組合起來決定行數,中間4bit組合起來決定列數,S盒也是DES中最有爭議的一部分,因為它的設計原則並未公開,被懷疑裝有後門,具體的S盒是這樣規定的:
| S1 | | | | | | | | | | | | | | | | |
| :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 14 | 4 | 13 | 1 | 2 | 15 | 11 | 8 | 3 | 10 | 6 | 12 | 5 | 9 | 0 | 7 |
| 0yyyy1 | 0 | 15 | 7 | 4 | 14 | 2 | 13 | 1 | 10 | 6 | 12 | 11 | 9 | 5 | 3 | 8 |
| 1yyyy0 | 4 | 1 | 14 | 8 | 13 | 6 | 2 | 11 | 15 | 12 | 9 | 7 | 3 | 10 | 5 | 0 |
| 1yyyy1 | 15 | 12 | 8 | 2 | 4 | 9 | 1 | 7 | 5 | 11 | 3 | 14 | 10 | 0 | 6 | 13 |
| S2 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 15 | 1 | 8 | 14 | 6 | 11 | 3 | 4 | 9 | 7 | 2 | 13 | 12 | 0 | 5 | 10 |
| 0yyyy1 | 3 | 13 | 4 | 7 | 15 | 2 | 8 | 14 | 12 | 0 | 1 | 10 | 6 | 9 | 11 | 5 |
| 1yyyy0 | 0 | 14 | 7 | 11 | 10 | 4 | 13 | 1 | 5 | 8 | 12 | 6 | 9 | 3 | 2 | 15 |
| 1yyyy1 | 13 | 8 | 10 | 1 | 3 | 15 | 4 | 2 | 11 | 6 | 7 | 12 | 0 | 5 | 14 | 9 |
| S3 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 10 | 0 | 9 | 14 | 6 | 3 | 15 | 5 | 1 | 13 | 12 | 7 | 11 | 4 | 2 | 8 |
| 0yyyy1 | 13 | 7 | 0 | 9 | 3 | 4 | 6 | 10 | 2 | 8 | 5 | 14 | 12 | 11 | 15 | 1 |
| 1yyyy0 | 13 | 6 | 4 | 9 | 8 | 15 | 3 | 0 | 11 | 1 | 2 | 12 | 5 | 10 | 14 | 7 |
| 1yyyy1 | 1 | 10 | 13 | 0 | 6 | 9 | 8 | 7 | 4 | 15 | 14 | 3 | 11 | 5 | 2 | 12 |
| S4 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 7 | 13 | 14 | 3 | 0 | 6 | 9 | 10 | 1 | 2 | 8 | 5 | 11 | 12 | 4 | 15 |
| 0yyyy1 | 13 | 8 | 11 | 5 | 6 | 15 | 0 | 3 | 4 | 7 | 2 | 12 | 1 | 10 | 14 | 9 |
| 1yyyy0 | 10 | 6 | 9 | 0 | 12 | 11 | 7 | 13 | 15 | 1 | 3 | 14 | 5 | 2 | 8 | 4 |
| 1yyyy1 | 3 | 15 | 0 | 6 | 10 | 1 | 13 | 8 | 9 | 4 | 5 | 11 | 12 | 7 | 2 | 14 |
| S5 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 2 | 12 | 4 | 1 | 7 | 10 | 11 | 6 | 8 | 5 | 3 | 15 | 13 | 0 | 14 | 9 |
| 0yyyy1 | 14 | 11 | 2 | 12 | 4 | 7 | 13 | 1 | 5 | 0 | 15 | 10 | 3 | 9 | 8 | 6 |
| 1yyyy0 | 4 | 2 | 1 | 11 | 10 | 13 | 7 | 8 | 15 | 9 | 12 | 5 | 6 | 3 | 0 | 14 |
| 1yyyy1 | 11 | 8 | 12 | 7 | 1 | 14 | 2 | 13 | 6 | 15 | 0 | 9 | 10 | 4 | 5 | 3 |
| S6 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 12 | 1 | 10 | 15 | 9 | 2 | 6 | 8 | 0 | 13 | 3 | 4 | 14 | 7 | 5 | 11 |
| 0yyyy1 | 10 | 15 | 4 | 2 | 7 | 12 | 9 | 5 | 6 | 1 | 13 | 14 | 0 | 11 | 3 | 8 |
| 1yyyy0 | 9 | 14 | 15 | 5 | 2 | 8 | 12 | 3 | 7 | 0 | 4 | 10 | 1 | 13 | 11 | 6 |
| 1yyyy1 | 4 | 3 | 2 | 12 | 9 | 5 | 15 | 10 | 11 | 14 | 1 | 7 | 6 | 0 | 8 | 13 |
| S7 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 4 | 11 | 2 | 14 | 15 | 0 | 8 | 13 | 3 | 12 | 9 | 7 | 5 | 10 | 6 | 1 |
| 0yyyy1 | 13 | 0 | 11 | 7 | 4 | 9 | 1 | 10 | 14 | 3 | 5 | 12 | 2 | 15 | 8 | 6 |
| 1yyyy0 | 1 | 4 | 11 | 13 | 12 | 3 | 7 | 14 | 10 | 15 | 6 | 8 | 0 | 5 | 9 | 2 |
| 1yyyy1 | 6 | 11 | 13 | 8 | 1 | 4 | 10 | 7 | 9 | 5 | 0 | 15 | 14 | 2 | 3 | 12 |
| S8 | | | | | | | | | | | | | | | | |
| | x0000x | x0001x | x0010x | x0011x | x0100x | x0101x | x0110x | x0111x | x1000x | x1001x | x1010x | x1011x | x1100x | x1101x | x1110x | x1111x |
| 0yyyy0 | 13 | 2 | 8 | 4 | 6 | 15 | 11 | 1 | 10 | 9 | 3 | 14 | 5 | 0 | 12 | 7 |
| 0yyyy1 | 1 | 15 | 13 | 8 | 10 | 3 | 7 | 4 | 12 | 5 | 6 | 11 | 0 | 14 | 9 | 2 |
| 1yyyy0 | 7 | 11 | 4 | 1 | 9 | 12 | 14 | 2 | 0 | 6 | 10 | 13 | 15 | 3 | 5 | 8 |
| 1yyyy1 | 2 | 1 | 14 | 7 | 4 | 10 | 8 | 13 | 15 | 12 | 9 | 0 | 3 | 5 | 6 | 11 |
例如“**0**1101**1**”的輸入的外側位為“**01**”,內側位為“1101”,即第2行,第14列。因此在S5中的對應輸出為“1001”(十進位制的9)
- **P置換**:P置換將S盒輸出的32位資料重新排列
| 16 | 7 | 20 | 21 |
| :--: | :--: | :--: | :--: |
| 29 | 12 | 28 | 17 |
| 1 | 15 | 23 | 26 |
| 5 | 18 | 31 | 10 |
| 2 | 8 | 24 | 14 |
| 32 | 27 | 3 | 9 |
| 19 | 13 | 30 | 6 |
| 22 | 11 | 4 | 25 |
置換後輸出的資料同本輪的左半部分異或成為新的右半部分,隨即作為輸入進入下一輪。
# 3 輪金鑰生成
上面提到,參與輪金鑰加的輪金鑰有48bit,但種子金鑰是有64bit的,生成輪金鑰主要要經過以下幾步:
## 3.1 選擇置換(PC-1)
在輸入的種子金鑰中,有8bit是不用於加密的,通常用於校驗或者直接捨棄掉,PC-1就是打亂順序的同時捨棄掉這些位元,觀察下表,首先可以注意到表中是沒有8、16、24這些位元的;此外,PC-1結束後金鑰被分為左右兩部分,如下表所示:
| 左 | | | | | | |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 57 | 49 | 41 | 33 | 25 | 17 | 9 |
| 1 | 58 | 50 | 42 | 34 | 26 | 18 |
| 10 | 2 | 59 | 51 | 43 | 35 | 27 |
| 19 | 11 | 3 | 60 | 52 | 44 | 36 |
| 右 | | | | | | |
| 63 | 55 | 47 | 39 | 31 | 23 | 15 |
| 7 | 62 | 54 | 46 | 38 | 30 | 22 |
| 14 | 6 | 61 | 53 | 45 | 37 | 29 |
| 21 | 13 | 5 | 28 | 20 | 12 | 4 |
# 3.2 迴圈移位
對每一輪操作,金鑰的左右兩部分會同時進行迴圈左移,每一輪迴圈左移的位數規定如下:
| 回次 | 左移位數 |
| :--: | :------: |
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 2 |
| 9 | 1 |
| 10 | 2 |
| 11 | 2 |
| 12 | 2 |
| 13 | 2 |
| 14 | 2 |
| 15 | 2 |
| 16 | 1 |
## 3.3 壓縮置換(PC-2)
每一次迴圈左移結束後,根據下表選出48bit作為輪金鑰,所以選擇置換2又被稱為壓縮置換:
| 14 | 17 | 11 | 24 | 1 | 5 |
| :--: | :--: | :--: | :--: | :--: | :--: |
| 3 | 28 | 15 | 6 | 21 | 10 |
| 23 | 19 | 12 | 4 | 26 | 8 |
| 16 | 7 | 27 | 20 | 13 | 2 |
| 41 | 52 | 31 | 37 | 47 | 55 |
| 30 | 40 | 51 | 45 | 33 | 48 |
| 44 | 49 | 39 | 56 | 34 | 53 |
| 46 | 42 | 50 | 36 | 29 | 32 |
這樣,每一輪都能得到一個單獨的輪金鑰用於輪金鑰加的操作。
解密時,只需要將輪金鑰序列反序使用即可
# 4 解密操作
開頭說過,DES時典型的Feistel結構,在直到金鑰的情況下很容易就能實現對稱解密。
最開始學習的時候,收AES的影響,我以為是每個操作都會有一個逆操作,相應的S盒也有一個逆S盒,但在我程式碼實現時我發現這是錯誤的,不像AES是基於有限域上的操作,DES的S盒是沒有逆操作的,這時我才明白,原來只需要一樣的步驟,只需要改變輪金鑰的順序就能實現解密操作,所以說,學習知識時還是要仔細思考,不能淺嘗輒止!
# 參考資料
1. 維基百科[DES](https://zh.wikipedia.org/wiki/資料加密標準)
2. [DES描述 NIST](http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf)
3. 密碼編碼學與網路安全原理與實踐(英文版)