http://www.hankcs.com/security/des-algorithm-illustrated.html
DES(Data Encryption Standard)算法是世界上最常用的加密算法。在很長時間內,許多人心目中“密碼生成”與DES一直是個同義詞。
DES是怎么工作的?本文通過一個簡單的例子來一部一部展示DES的加密流程。自動DES誕生以來,許多加密算法都采用了類似DES的手段。一旦理解了DES中的變換,你一定能夠更輕松的理解這些現代加密算法中的門道。
DES處理比特,或者說二進制數字,我們知道,沒四個比特構成一個十六進制數。DES加密一組64位的信息,也就是16個16進制數。為了完成加密,DES
DES秘鑰獲取:
我們取16進制秘鑰K為:
K = 133457799BBCDFF1
我們可以得到他的二進制形式(1為0001,3為0011,依次類推,並且將沒8位寫成一組。這樣每組的最后一位都沒有被用上。)
K = 00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001
創建16個子秘鑰,每個長48比特
這個64位的秘鑰首先根據表格PC-1進行變換。
表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 |
由於上表中第一個元素為57,這將使元秘鑰的第57位變換為新秘鑰K+的第一位。同理,元秘鑰的第49位變換為新秘鑰的第2位,,,元秘鑰的第4位變換為新秘鑰的最后一位,注意元秘鑰中只有56位會進入新秘鑰,上表也只有56個元素。
比如,對於原秘鑰:
K = 00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001
我們將得到56位新秘鑰:
K+ = 1111000 0110011 0010101 0101111 0101010 1011001 1001111 0001111
然后,我們將這個密鑰拆分為左右兩個部分,C0和D0,每半邊都有28位。
比如,對於新密鑰,我們得到:
C0 = 1111000 0110011 0010101 0101111
D0 = 0101010 1011001 1001111 0001111
對於相同定義的C0和D0,我們現在創建16個塊Cn和Dn 1<=n<=16.
每一對Cn和Dn都是由前一對Cn-1和Dn-1移位而來。具體來說,對於n=1,2,3,。。。,16,在前一輪移位的結果上,進行左移操作。什么叫左移?左移指的是將除第一位外的所有為往左移一位,將第一位移動至最后一位。
這意味着,比如說,C3和D3是C2和D2移位而來的,具體來說,通過2次左移位,C16和D16則是由C15和D15通過1次左移得到的。在所有情況下,一次左移就是將所有比特往左移動一位。使的一位后的比特的位置相較於變換前成為2,3,4,,,28,1.
比如,對於原始字謎要C0和D0,我們得到:
C0 = 1111000011001100101010101111 C1 = 1110000110011001010101011111 C2 = 1100001100110010101010111111 C3 = 0000110011001010101011111111 C4 = 0011001100101010101111111100 C5 = 1100110010101010111111110000 C6 = 0011001010101011111111000011 C7 = 1100101010101111111100001100 C8 = 0010101010111111110000110011 C9 = 0101010101111111100001100110 C10 = 0101010111111110000110011001 C11 = 0101011111111000011001100101 C12 = 0101111111100001100110010101 C13 = 0111111110000110011001010101 C14 = 1111111000011001100101010101 C15 = 1111100001100110010101010111 C16 = 1111000011001100101010101111 D0 = 0101010101100110011110001111 D1 = 1010101011001100111100011110 D2 = 0101010110011001111000111101 D3 = 0101011001100111100011110101 D4 = 0101100110011110001111010101 D5 = 0110011001111000111101010101 D6 = 1001100111100011110101010101 D7 = 0110011110001111010101010110 D8 = 1001111000111101010101011001 D9 = 0011110001111010101010110011 D10 = 1111000111101010101011001100 D11 = 1100011110101010101100110011 D12 = 0001111010101010110011001111 D13 = 0111101010101011001100111100 D14 = 1110101010101100110011110001 D15 = 1010101010110011001111000111 D16 = 0101010101100110011110001111
我們現在就可以得到第n輪的新秘鑰Kn(1<=n<=16)了。具體做法是,對每一對拼合后的子秘鑰CnDn,按照表PC-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 |
每對子秘鑰有56位,但是PC-2僅僅使用其中48位。
於是,第你輪新秘鑰Kn的第一位來自組合秘鑰CnDn的第14位,第2位來自第17位,以此類推,知道新秘鑰的第48位來自組合秘鑰的第32位。
比如:
對於第一輪的組合秘鑰,我們有:
C1D1 = 1110000 1100110 0101010 1011111 1010101 0110011 0011110 0011110
通過PC-2的變換后,得到:
K1 = 000110 110000 001011 101111 111111 000111 000001 110010
同理,對於其他秘鑰,我們得到:
K2 = 011110 011010 111011 011001 110110 111100 100111 100101 K3 = 010101 011111 110010 001010 010000 101100 111110 011001 K4 = 011100 101010 110111 010110 110110 110011 010100 011101 K5 = 011111 001110 110000 000111 111010 110101 001110 101000 K6 = 011000 111010 010100 111110 010100 000111 101100 101111 K7 = 111011 001000 010010 110111 111101 100001 100010 111100 K8 = 111101 111000 101000 111010 110000 010011 101111 111011 K9 = 111000 001101 101111 101011 111011 011110 011110 000001 K10 = 101100 011111 001101 000111 101110 100100 011001 001111 K11 = 001000 010101 111111 010011 110111 101101 001110 000110 K12 = 011101 010111 000111 110101 100101 000110 011111 101001 K13 = 100101 111100 010111 010001 111110 101011 101001 000001 K14 = 010111 110100 001110 110111 111100 101110 011100 111010 K15 = 101111 111001 000110 001101 001111 010011 111100 001010 K16 = 110010 110011 110110 001011 000011 100001 011111 110101
關於子秘鑰的話題我們就到此為止,接下來我們看信息本身。
DES是一個基於組塊的加密算法,這意味着無論輸入還是輸出都是64位長度。也就是說DES產生了一種最多264中的變換方法。每個64位的區塊被分為2個32位的部分,左半部分L和右半部分R。
比如明文,M為
M = 0123456789ABCDEF
這里的M是16進制的,將M寫成二進制,我們得到一個64位的區塊:
M = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 L = 0000 0001 0010 0011 0100 0101 0110 0111 R = 1000 1001 1010 1011 1100 1101 1110 1111
M的第一位是0,最后一位是1,我們從左讀到右。
對於明文M,我們計算一下初始變換IP(Initial permutation)。IP是重新變換數據M的每一位產生的。產生過程由下表決定,表格的下標對應新數據的下標,表格的數值x表示新數據的這一位來自舊數據的第x位。
比如,對M的區塊,執行初始變換,得到:
M = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
IP = 1100 1100 0000 0000 1100 1100 1111 1111 1111 0000 1010 1010 1111 0000 1010 1010
接着講變換IP分為32位的左半邊L0和右半邊R0
比如,對於上例,我們得到:
L0 = 1100 1100 0000 0000 1100 1100 1111 1111
R0 = 1111 0000 1010 1010 1111 0000 1010 1010
我們接着執行16個迭代,對1<=n<=16,使用一個函數f.函數f輸入兩個區塊,一個32位的數據塊和一個48位的木曜區塊Kn,輸出一個32位的區塊。定義+表示異或XOR。那么讓n從1循環到16,我們計算:
Ln=Rn-1
Rn=Ln-1+f(Rn-1,Kn)
這樣我們就得到最終區塊,也就是n=16的L16R16.這個過程說白了就是,我們那前一個迭代結果的右邊32位作為當前迭代的左邊32位。對於當前迭代的右邊32位,將它和上一個迭代的f函數的輸出執行XOR運算。
比如,對於n=1,我們有:
K1 = 000110 110000 001011 101111 111111 000111 000001 110010 L1 = R0 = 1111 0000 1010 1010 1111 0000 1010 1010 R1 = L0 + f(R0,K1)
剩下就是f函數是如何工作的了,為了計算f,我們首先擴展每個Rn-1,將其從32位擴展到48位,這是通過使用一張表來重復Rn-1中的一位位來實現的。我們稱這個過程為函數E。也就是說函數E(Rn-1)輸入32位輸出48位。
定義E為函數E的輸出,將其寫成8組,每組6位,這些比特是通過選擇輸入的某些位來產的,具體選擇順序按照如下表格實現:
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 |
也就是說E(Rn-1)開頭的三個比特分別來自Rn-1的第32、1和2位。E(Rn-1)末尾的2個比特分別來自Rn-1的第32位和第1位。
比如:給定R0,我們可以計算出E(R0):
R0 = 1111 0000 1010 1010 1111 0000 1010 1010
E(R0) = 011110 100001 010101 010101 011110 100001 010101 010101
接着在f函數中,我們對輸出E(Rn-1)和秘鑰Kn執行XOR運算:
Kn+E(Rn-1)
比如,對K1,E(R0),我們有:
K1 = 000110 110000 001011 101111 111111 000111 000001 110010 E(R0) = 011110 100001 010101 010101 011110 100001 010101 010101 K1+E(R0) = 011000 010001 011110 111010 100001 100110 010100 100111
到這里我們還沒有完成f函數的運算,我們僅僅使用一張表將Rn-1從32位擴展為48位,並且對這個結果和秘鑰Kn執行了異或運算。我們現在有了48位的結果,或者說8組6比特數據。我們現在要對每組的6比特執行一些奇怪的操作:
我們將它作為一張被稱為“S盒”的表格的地址。每組6比特都將給我們一個位於不同S盒中的地址。在哪個地址里存放着一個4比特的數字。這個4比特的數字將會替換掉原來的6個比特。最終結果就是,8組6比特的數據被轉換為8組4比特(一共32位)的數據。
將上一步的48位的結果寫成如下形式:
Kn+E(Rn-1)=B1B2B3B4B5B6B7B8
每個Bi都是一個6比特的分組,我們現在計算
S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8)
其中,Si(Bi)指的是第i個S盒的輸出。
為了計算每個S函數S1,S2,,,S8,取一個6位的區塊作為輸入,輸出一個4位的區塊。決定S1的表格如下:
S1Column Number
Row | ||||||||||||||||
No. | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
0 | 14 | 4 | 13 | 1 | 2 | 15 | 11 | 8 | 3 | 10 | 6 | 12 | 5 | 9 | 0 | 7 |
1 | 0 | 15 | 7 | 4 | 14 | 2 | 13 | 1 | 10 | 6 | 12 | 11 | 9 | 5 | 3 | 8 |
2 | 4 | 1 | 14 | 8 | 13 | 6 | 2 | 11 | 15 | 12 | 9 | 7 | 3 | 10 | 5 | 0 |
3 | 15 | 12 | 8 | 2 | 4 | 9 | 1 | 7 | 5 | 11 | 3 | 14 | 10 | 0 | 6 | 13 |
如果S1是定義在這張表上的函數,B是一個6位的塊,那么計算S1(B)的方法是:B的第一位和最后一位組合起來,的二進制數決定一個介於0和3之間的十進制數(或者二進制00到11之間)。設這個數為i,B的中間4位二進制數代表一個介於0到15之間的二進制數(二進制0000到1111)。設這個數為j。查表找到第i行第j列的那個數,這個是一個介於0和15之間的數,並且它是能由一個唯一的4位區塊表示的。這個區塊就是函數S1輸入B得到的輸出S1(B)。比如,對輸入B=011011,第一位是0,最后一位是1,決定了行號是01,也就是十進制的1,中間4位是1101,也就是十進制的13,雖有列號是13.查表第一行第13列我們得到數字5.
這就決定了輸出;5的二進制是0101,所以輸出就是0101,即S1(011011)=0101。
同理,定義這8個函數S1,S2,,,S8:
14 | 4 | 13 | 1 | 2 | 15 | 11 | 8 | 3 | 10 | 6 | 12 | 5 | 9 | 0 | 7 |
0 | 15 | 7 | 4 | 14 | 2 | 13 | 1 | 10 | 6 | 12 | 11 | 9 | 5 | 3 | 8 |
4 | 1 | 14 | 8 | 13 | 6 | 2 | 11 | 15 | 12 | 9 | 7 | 3 | 10 | 5 | 0 |
15 | 12 | 8 | 2 | 4 | 9 | 1 | 7 | 5 | 11 | 3 | 14 | 10 | 0 | 6 | 13 |
15 | 1 | 8 | 14 | 6 | 11 | 3 | 4 | 9 | 7 | 2 | 13 | 12 | 0 | 5 | 10 |
3 | 13 | 4 | 7 | 15 | 2 | 8 | 14 | 12 | 0 | 1 | 10 | 6 | 9 | 11 | 5 |
0 | 14 | 7 | 11 | 10 | 4 | 13 | 1 | 5 | 8 | 12 | 6 | 9 | 3 | 2 | 15 |
13 | 8 | 10 | 1 | 3 | 15 | 4 | 2 | 11 | 6 | 7 | 12 | 0 | 5 | 14 | 9 |
10 | 0 | 9 | 14 | 6 | 3 | 15 | 5 | 1 | 13 | 12 | 7 | 11 | 4 | 2 | 8 |
13 | 7 | 0 | 9 | 3 | 4 | 6 | 10 | 2 | 8 | 5 | 14 | 12 | 11 | 15 | 1 |
13 | 6 | 4 | 9 | 8 | 15 | 3 | 0 | 11 | 1 | 2 | 12 | 5 | 10 | 14 | 7 |
1 | 10 | 13 | 0 | 6 | 9 | 8 | 7 | 4 | 15 | 14 | 3 | 11 | 5 | 2 | 12 |
7 | 13 | 14 | 3 | 0 | 6 | 9 | 10 | 1 | 2 | 8 | 5 | 11 | 12 | 4 | 15 |
13 | 8 | 11 | 5 | 6 | 15 | 0 | 3 | 4 | 7 | 2 | 12 | 1 | 10 | 14 | 9 |
10 | 6 | 9 | 0 | 12 | 11 | 7 | 13 | 15 | 1 | 3 | 14 | 5 | 2 | 8 | 4 |
3 | 15 | 0 | 6 | 10 | 1 | 13 | 8 | 9 | 4 | 5 | 11 | 12 | 7 | 2 | 14 |
2 | 12 | 4 | 1 | 7 | 10 | 11 | 6 | 8 | 5 | 3 | 15 | 13 | 0 | 14 | 9 |
14 | 11 | 2 | 12 | 4 | 7 | 13 | 1 | 5 | 0 | 15 | 10 | 3 | 9 | 8 | 6 |
4 | 2 | 1 | 11 | 10 | 13 | 7 | 8 | 15 | 9 | 12 | 5 | 6 | 3 | 0 | 14 |
11 | 8 | 12 | 7 | 1 | 14 | 2 | 13 | 6 | 15 | 0 | 9 | 10 | 4 | 5 | 3 |
12 | 1 | 10 | 15 | 9 | 2 | 6 | 8 | 0 | 13 | 3 | 4 | 14 | 7 | 5 | 11 |
10 | 15 | 4 | 2 | 7 | 12 | 9 | 5 | 6 | 1 | 13 | 14 | 0 | 11 | 3 | 8 |
9 | 14 | 15 | 5 | 2 | 8 | 12 | 3 | 7 | 0 | 4 | 10 | 1 | 13 | 11 | 6 |
4 | 3 | 2 | 12 | 9 | 5 | 15 | 10 | 11 | 14 | 1 | 7 | 6 | 0 | 8 | 13 |
4 | 11 | 2 | 14 | 15 | 0 | 8 | 13 | 3 | 12 | 9 | 7 | 5 | 10 | 6 | 1 |
13 | 0 | 11 | 7 | 4 | 9 | 1 | 10 | 14 | 3 | 5 | 12 | 2 | 15 | 8 | 6 |
1 | 4 | 11 | 13 | 12 | 3 | 7 | 14 | 10 | 15 | 6 | 8 | 0 | 5 | 9 | 2 |
6 | 11 | 13 | 8 | 1 | 4 | 10 | 7 | 9 | 5 | 0 | 15 | 14 | 2 | 3 | 12 |
13 | 2 | 8 | 4 | 6 | 15 | 11 | 1 | 10 | 9 | 3 | 14 | 5 | 0 | 12 | 7 |
1 | 15 | 13 | 8 | 10 | 3 | 7 | 4 | 12 | 5 | 6 | 11 | 0 | 14 | 9 | 2 |
7 | 11 | 4 | 1 | 9 | 12 | 14 | 2 | 0 | 6 | 10 | 13 | 15 | 3 | 5 | 8 |
2 | 1 | 14 | 7 | 4 | 10 | 8 | 13 | 15 | 12 | 9 | 0 | 3 | 5 | 6 | 11 |
例子:對弈第一輪,我們得到這8個S盒的輸出:
K1+E(R0)=011000 010001 011110 111010 100001 100110 010100 100111
S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8)=0101 1100 1000 0010 1011 0101 1001 0111
函數f的最后一步就是對S盒的輸出進行一個變換來產生最終值:
f=P(S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8))
變換P由如下表格定義。P輸入32位數據,通過下表產生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
比如對8個S盒的輸出:
S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8)=0101 1100 1000 0010 1011 0101 1001 0111
我們得到:
f=0010 0011 0100 1010 1010 1001 1011 1011
那么R1=L0+f(R0,K1)
= 1100 1100 0000 0000 1100 1100 1111 1111 + 0010 0011 0100 1010 1010 1001 1011 1011 = 1110 1111 0100 1010 0110 0101 0100 0100
在下一輪迭代中,我們的L2=R1,這就是我們剛剛計算的結果。之后,我們必須計算R2=L1+f(R1,K2),一直完成16個迭代之后,我們有了區塊L16和R16,。接着我們逆轉兩個區塊的順序得到一個64位的區塊:
R16L16
然后,我們對其執行一個最終的IP-1,其定義如下:
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 |
也就是說,該變換的輸出的第一位是輸入的第40位,第二位是輸入的8位,一直到將輸入的第25位作為輸出的最后一位。
比如,我們使用上述方法得到了第16輪的左右兩個區塊:
L16 = 0100 0011 0100 0010 0011 0010 0011 0100
R16 = 0000 1010 0100 1100 1101 1001 1001 0101
我們將兩個區塊調換位置,然后執行最終變換:
R16L16 = 00001010 01001100 11011001 10010101 01000011 01000010 00110010 00110100
IP-1 = 10000101 11101000 00010011 01010100 00001111 00001010 10110100 00000101
寫成16進制得到:
85E813540F0AB405
這就是明文M=0123456789ABCDEF的密文:85E813540F0AB405
解密就是加密的反過程,執行上述步驟,只不過在那16輪迭代中,調轉左右子秘鑰的位置而已。