对称加密算法"/>
初学者最易理解的DES对称加密算法
最近刚接触密码学,这是我仔细研究DES对称密码总结的一篇文章,我用最适合初学者的语言记录下我的算法以及心得,也有实例帮助理解,希望能够帮助到您更快速的、更容易接触并掌握DES。甘八烈!
DES对称加密算法举例详解
DES加解密介绍:
1.如果我们手上有一段明文:8787878787878787
2.选取DES密钥:0E329232EA6D0D73
3.我们就能得到密文:0000000000000000
4.如果对上述密文使用相同的DES密钥(0E329232EA6D0D73)来解密的话,我们就能得到原来的明文:8787878787878787
DES加解密详细流程:
第一步:创建16个子密钥,每个长48比特
一.取明文:0123456789ABCDEF
二.这里的M是16进制的,将M写成3二进制,我们得到一个64位的区块:
M=0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
三.然后我们取十六进制的秘钥:K=133457799BBCDFF1
秘钥K的第8, 16, 24, 32, 40, 48, 56,和64位去掉,因为机器需要这8位作为奇偶位,我们也可按照下表进行置换(注意:表中的每位数字代表M中的位数):
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位变换为新秘钥K+的第1位。同理,原秘钥的第49位变换为新秘钥的第2位……原秘钥的第4位变换为新秘钥的最后一位。注意原秘钥中只有56位会进入新秘钥,上表也只有56个元素。
因此,原64位的秘钥为: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
五.对每位进行左移,即将除第一位外的所有位往左移一位,将第一位移动至最后一位。了解了左移之后,我们便可以按照下表对应的位数进行左移(1,2,9,16位每位左移一位,其余位左移2位)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1
这意味着,比如说,C3 and D3是C2 and D2移位而来的,具体来说,通过2次左移位;C16 and D16 则是由C15 and D15通过1次左移得到的。在所有情况下,一次左移就是将所有比特往左移动一位,使得移位后的比特的位置相较于变换前成为2, 3,…, 28, 1。
比如,对于原始子秘钥C0 anD D0,我们得到:
(1). C0 = 1111000011001100101010101111
(2). D0 = 0101010101100110011110001111
(3). C1 = 1110000110011001010101011111
(4). D1 = 1010101011001100111100011110
(5). C2 = 1100001100110010101010111111
(6). D2 = 0101010110011001111000111101
(7). C3 = 0000110011001010101011111111
(8). D3 = 0101011001100111100011110101
(9). C4 = 0011001100101010101111111100
(10).D4 = 0101100110011110001111010101
(11).C5 = 1100110010101010111111110000
(12).D5 = 0110011001111000111101010101
(13).C6 = 0011001010101011111111000011
(14).D6 = 1001100111100011110101010101
(15).C7 = 1100101010101111111100001100
(16).D7 = 0110011110001111010101010110
(17).C8 = 0010101010111111110000110011
(18).D8 = 1001111000111101010101011001
(19).C9 = 0101010101111111100001100110
(20).D9 = 0011110001111010101010110011
(21).C10 = 0101010111111110000110011001
(22).D10 = 1111000111101010101011001100
(23).C11 = 0101011111111000011001100101
(24).D11 = 1100011110101010101100110011
(25).C12 = 0101111111100001100110010101
(26).D12 = 0001111010101010110011001111
(27).C13 = 0111111110000110011001010101
(28).D13 = 0111101010101011001100111100
(29).C14 = 1111111000011001100101010101
(30).D14 = 1110101010101100110011110001
(31).C15 = 1111100001100110010101010111
(32).D15 = 1010101010110011001111000111
(33).C16 = 1111000011001100101010101111
(34).D16 = 0101010101100110011110001111
我们现在就可以得到第n轮的新秘钥Kn( 1<=n<=16)了。具体做法是,对每对拼合后的子秘钥CnDn,按下表PC-2执行变换:
PC-2
14 17 11 24 1 53 28 15 6 21 1023 19 12 4 26 816 7 27 20 13 241 52 31 37 47 5530 40 51 45 33 4844 49 39 56 34 5346 42 50 36 29 32
每对子秘钥有56位,但PC-2仅仅使用其中的48位。于是,第n轮的新秘钥Kn 的第1位来自组合子秘钥CnDn的第14位,第2位来自第17位,依次类推,直到新秘钥的第48位来自组合秘钥的第32位。
比如,对于第1轮的组合秘钥,我们有:
-
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
10.K10 = 101100 011111 001101 000111 101110 100100 011001 001111
11.K11 = 001000 010101 111111 010011 110111 101101 001110 000110
12.K12 = 011101 010111 000111 110101 100101 000110 011111 101001
13.K13 = 100101 111100 010111 010001 111110 101011 101001 000001
14.K14 = 010111 110100 001110 110111 111100 101110 011100 111010
15.K15 = 101111 111001 000110 001101 001111 010011 111100 001010
16.K16 = 110010 110011 110110 001011 000011 100001 011111 110101
关于创建16长度为48位的子秘钥的话题就到此为止了,接下来我们看看信息本身。
第二步:加密数据的每个64位区块:
一.对于明文数据M,我们计算一个初始变换IP。IP是重新变换数据M的每一位产生的。产生过程由下表决定,表格的下标对应新数据的下标,表格的数值x表示新数据的这一位来自旧数据的第x位。
IP58 50 42 34 26 18 10 260 52 44 36 28 20 12 462 54 46 38 30 22 14 664 56 48 40 32 24 16 857 49 41 33 25 17 9 159 51 43 35 27 19 11 361 53 45 37 29 21 13 563 55 47 39 31 23 15 7
按照上表,M的第58位成为IP的第1位,M的第50位成为IP的第2位,M的第7位成为IP的最后一位。
如,对M的区块执行初始变换,得到:
1.M = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
2.IP = 1100 1100 0000 0000 1100 1100 1111 1111 1111 0000 1010 1010 1111 0000 1010 1010
这里M的第58位是1,变成了IP的第1位。M的第50位是1,变成了IP的第2位。M的第7位是0,变成了IP的最后一位。
接着讲变换IP分为32位的左半边L0 和32位的右半边R0 。
比如,对于上例,我们得到:
1.L0 = 1100 1100 0000 0000 1100 1100 1111 1111
2.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位。这些比特是通过选择输入的某些位来产生的,具体选择顺序按下表实现:
E BIT-SELECTION TABLE
32 1 2 3 4 54 5 6 7 8 98 9 10 11 12 1312 13 14 15 16 1716 17 18 19 20 2120 21 22 23 24 2524 25 26 27 28 2928 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
(注意输入的每4位一个分组被拓展为输出的每6位一个分组。)
接着在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的表格如下:
S1
Column 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。查表第1行第13列我们得到数字5。这决定了输出;5是二进制0101,所以输出就是0101。也即S1(011011) = 0101。同理,定义这8个函数S1,…,S8的表格如下所示:
S1
14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 70 15 7 4 14 2 13 1 10 6 12 11 9 5 3 84 1 14 8 13 6 2 11 15 12 9 7 3 10 5 015 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13S215 1 8 14 6 11 3 4 9 7 2 13 12 0 5 103 13 4 7 15 2 8 14 12 0 1 10 6 9 11 50 14 7 11 10 4 13 1 5 8 12 6 9 3 2 1513 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9S310 0 9 14 6 3 15 5 1 13 12 7 11 4 2 813 7 0 9 3 4 6 10 2 8 5 14 12 11 15 113 6 4 9 8 15 3 0 11 1 2 12 5 10 14 71 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12S47 13 14 3 0 6 9 10 1 2 8 5 11 12 4 1513 8 11 5 6 15 0 3 4 7 2 12 1 10 14 910 6 9 0 12 11 7 13 15 1 3 14 5 2 8 43 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14S52 12 4 1 7 10 11 6 8 5 3 15 13 0 14 914 11 2 12 4 7 13 1 5 0 15 10 3 9 8 64 2 1 11 10 13 7 8 15 9 12 5 6 3 0 1411 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3S612 1 10 15 9 2 6 8 0 13 3 4 14 7 5 1110 15 4 2 7 12 9 5 6 1 13 14 0 11 3 89 14 15 5 2 8 12 3 7 0 4 10 1 13 11 64 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13S74 11 2 14 15 0 8 13 3 12 9 7 5 10 6 113 0 11 7 4 9 1 10 14 3 5 12 2 15 8 61 4 11 13 12 3 7 14 10 15 6 8 0 5 9 26 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12S813 2 8 4 6 15 11 1 10 9 3 14 5 0 12 71 15 13 8 10 3 7 4 12 5 6 11 0 14 9 27 11 4 1 9 12 14 2 0 6 10 13 15 3 5 82 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)…S8(B8))
变换P由如下表格定义。P输入32位数据,通过下标产生32位输出:
P
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
也就是说,该变换的的输出的第1位是输入的第40位,第2位是输入的第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的加密形式C = 85E813540F0AB405。
解密就是加密的反过程,执行上述步骤,只不过在那16轮迭代中,调转左右子秘钥的位置而已。
更多推荐
初学者最易理解的DES对称加密算法
发布评论