背景简介
DES(Data Encryption Standard)算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。
特点
优点:算法公开、计算量小、加解密速度快、效率高
缺点:分组内容短、密钥短、密码生命周期短、运算速度较慢。
原理概述
通过输入的密钥、明文和模式经过16轮DES加密最终输出由多个64位二进制片段组成的加密二进制字符串。流程图如下:
本篇文章将主要讲解上图虚线框中DES加密过程的原理。
原理详解
DES加密操作分两部分:生成子密钥和明文加密。
生成子密钥:
流程图:
1、输入64位密钥
// 随机输入一个64位密钥:
0 0 1 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 0 0 1 0 1 0
2、将输入的密钥通过密钥置换表(下图)进行密钥置换:
64位密钥中的第8、16、24、32、40、48、56、64这8个校验位不参与置换,所以根据图表,最后会生成一个56位的密钥。置换的方法是将64位密钥中的第57位换到第1位,第49位换到第2位,以此类推,第4位换到第56位,最终完成置换。
// 置换后的内容如下:
0 1 0 0 0 0 1 0 1 0 0 1 1 1
0 0 0 1 1 0 0 0 1 1 0 1 0 0
1 1 1 0 0 1 1 1 0 1 0 0 0 0
1 0 1 1 0 0 0 1 1 0 0 0 1 0
3、将置换过后的密钥分成两部分:C-28 和 D-28,每部分28位。将这两部分通过移位表(下图)进行移位:
根据轮数,这两部分分别向左移动1位或2位。移位的方法是第1轮循环中C-28 和 D-28两部分均向左移动1位,第2轮循环中左右两部分均向左移动1位,以此类推,一直到第16轮循环结束,移位全部完成。
// 分成两部分:
// C-28
0 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 1 0 0
// D-28
1 1 1 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 0 1 0
// 比如第一轮移位向左移动1位,结果为:
// C-28
0 0 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 1 0
// D-28
0 1 1 1 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 0 1
4、将移位后的两部分拼接起来,得到56位长度的密钥。首先会将该密钥复制出两份,一份等待进入下一轮循环时使用,另一份通过压缩置换表(如下图)压缩成48位密钥,准备和该轮循环中的明文组进行异或操作:
56位密钥中的第9,18,22,25,35,38,43,54这8个校验位不参与置换,所以根据图标,最后会生成48位的密钥。置换的方法是将56位密钥中的第14位换到第1位,以此类推,将56位密钥中的第32位换到第48位,最终完成置换。(该方法和上述2中的置换原理相同)
// 移位后将C-28 和 D-28两部分拼接起来:
0 0 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 0 1
// 进行压缩置换后得到48位的结果:
1 0 0 1 0 0
1 0 1 0 0 1
0 1 0 0 0 1
0 0 1 1 1 0
0 1 1 1 1 0
1 0 1 0 0 0
1 0 1 1 0 0
1 0 0 1 0 1
明文加密:
流程图:
1、输入明文
// 假设输入的内容为 ‘Whale Idea’
2、对输入的明文进行补位操作。补位操作是为了保证加密时被拆分的每一组数据都是64位,具体补位方式如下:
- 加密前:明文字节长度对8取余,余数为m,补足8-m个字节数目,字节内容为8-m。
- 解密后:取最后一个字节,值为m,则从数据尾部向前删除m个字节数目,剩余数据即为加密前的原文。
例1:加密字符串为为AAA,则补位为AAA55555,解密后,取最后一个数字5,向前删除5个,最终得到AAA; 例2:加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888,解密后,取最后一个数字8,向前删除8个,最终得到CCCCCCCC
// 对‘Whale Idea’ 进行补位操作以后
‘Whale Idea’.length % 8 = 2 // 空格也算一个字节
// 因此需要在’Whale Idea‘后面添加(8-2)个(8-2),即6个6,最终得到:
‘Whale Idea666666’ // 完成补位
3、将补位后的明文转成二进制,然后分成每64位一组。
// 将‘Whale Idea222222’转换位二进制(https://codebeautify.org/string-binary-converter):
01010111 01101000 01100001 01101100 01100101 00100000 01001001 01100100 // 第一组64位
01100101 01100001 00110010 00110010 00110010 00110010 00110010 00110010 // 第二组64位
// 下面讲解中使用第一组进行举例
0 1 0 1 0 1 1 1
0 1 1 0 1 0 0 0
0 1 1 0 0 0 0 1
0 1 1 0 1 1 0 0
0 1 1 0 0 1 0 1
0 0 1 0 0 0 0 0
0 1 0 0 1 0 0 1
0 1 1 0 0 1 0 0
4、将每组64位明文内容根据初始置换表(下图)进行置换:
将上一步得到的64位二进制字符串中的第58位换到第1位,以此类推,没有不参与置换的校验位,置换完成后,依然是64位。
// 初始置换后的结果为:
1 1 0 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 1 1 0 0 1
0 1 0 1 0 1 0 1
0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 0
0 1 0 0 1 0 1 0
0 0 0 0 0 0 0 1
5、将置换后的64位明文组拆分成两部分:L-32和R-32,每部分32位。其中,将右半部分复制出两份(复制出R-32'和R-32''),R-32'会在下一次循环中成为左半部分的内容L-32,R-32''会进行一系列操作,然后和当前循环论次中的L-32进行一次异或操作,在下一次循环中成为右半部分的内容R-32。
// 将置换后的64位明文组拆分成两部分:
// L-32
1 1 0 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 1 1 0 0 1
0 1 0 1 0 1 0 1
// R-32
0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 0
0 1 0 0 1 0 1 0
0 0 0 0 0 0 0 1
// 复制出R-32‘,在下一次循环中成为左半部分的内容L-32
0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 0
0 1 0 0 1 0 1 0
0 0 0 0 0 0 0 1
// 复制出R-32‘‘,继续下面的一系列操作
0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 0
0 1 0 0 1 0 1 0
0 0 0 0 0 0 0 1
// 为方便演示下一步扩展操作,将R-32‘‘排列成4*8的形式
0 0 0 0
0 0 0 0
1 0 1 1
1 1 1 0
0 1 0 0
1 0 1 0
0 0 0 0
0 0 0 1
下面开始就是将R-32进行一系列操作的过程:
6、根据扩展置换表(如下)扩展为48位,
如上图,将原来的32位扩展为48位,扩展方式就是在第4、5位中间依次加入第5、4位的内容,在8、9位中间依次加入第9、8位的内容,以此类推,在第1位后加入第32位的内容,在第32位后加入第1位的内容,最终得到了48位,并和上述子密钥加密过程中生成的48位密钥进行异或操作。
// 第一列和最后一列为扩展内容:
1 0 0 0 0 0
0 0 0 0 0 1
0 1 0 1 1 1
1 1 1 1 0 0
0 0 1 0 0 1
0 1 0 1 0 0
0 0 0 0 0 0
0 0 0 0 1 0
// 和上面已经生成的48位密钥进行异或操作([https://www.23bei.com/tool-531.html](https://www.23bei.com/tool-531.html)):
// 密钥
1 0 0 1 0 0
1 0 1 0 0 1
0 1 0 0 0 1
0 0 1 1 1 0
0 1 1 1 1 0
1 0 1 0 0 0
1 0 1 1 0 0
1 0 0 1 0 1
// 结果为:
0 0 0 1 0 0
1 0 1 0 0 0
0 0 0 1 1 0
1 1 0 0 1 0
0 1 0 1 1 1
1 1 1 1 0 0
1 0 1 1 0 0
1 0 0 1 1 1
7、将上述异或操作的结果进行一次盒代替运算,目的是为了将目前的48位转换成32位,以便后面和L-32进行异或操作,盒代替规则如下:
将48位分成每6位一组,共8组,每组通过下图中的盒代替运算后输出4位,最终得到32位。
例如(进制换算:tool.lu/hexconvert/ ):
第一组内容为红框中选中的部分“000100”,我们分别取第1位和第6位拼成“00”作为第一部分,中间剩下的是“0010”作为第二部分。其中,将第一部分“00”换算成十进制数字“0”作为查找S盒中表格的行号,将第二部分“0010”换算成十进制数字“2”作为查找S盒中表格的列号。
上图中的每一组S-box对应一个表格,一共有8个表格(如下图),以S盒1举例,根据刚才所得行号(0)和列号(2)(行、列均从0开始计数)查到相应的十进制数字4(下图中红框标注部分),再将该数字转换成4位二进制(0100),最终完成盒代替运算。
以此类推,剩下的7个盒子也都是通过这种方法得到4位的结果,最终完成盒代替操作。也可以将盒置换看成一个压缩操作,将48位压缩成32位。
// 盒置换过程为:
// 1、拆分:
0 0 0 1 0 0 => 00 0010
1 0 1 0 0 0 => 10 0100
0 0 0 1 1 0 => 00 0011
1 1 0 0 1 0 => 10 1001
0 1 0 1 1 1 => 01 1011
1 1 1 1 0 0 => 10 1110
1 0 1 1 0 0 => 10 0110
1 0 0 1 1 1 => 11 0011
// 转换为十进制得到行号和列号
00 0010 => 0 2
10 0100 => 2 4
00 0011 => 0 3
10 1001 => 2 9
01 1011 => 1 11
10 1110 => 2 14
10 0110 => 2 6
11 0011 => 3 3
// 根据S盒插到对应十进制数字
//行 列
0 2 => 4 // S盒1
2 4 => 10
0 3 => 1
2 9 => 1
1 11 => 13
2 14 => 11
2 6 => 7
3 3 => 7
// 将查到的十进制数字转换为4位二进制:
4 => 0100
10 => 1010
1 => 0001
1 => 0001
13 => 1101
11 => 1011
7 => 0111
7 => 0111
// 得到最终置换后的结果:
0 1 0 0 1 0 1 0
0 0 0 1 0 0 0 1
1 1 0 1 1 0 1 1
0 1 1 1 0 1 1 1
8、将上述压缩后的R-32位根据盒置换表(如下图)再进行一次盒置换操作:
置换原理和上述初始置换方式相同。
// 置换结果为:
1 1 1 1 0 1 1 1
0 0 1 1 1 1 1 0
1 0 1 0 1 1 0 0
0 0 1 0 0 0 0 0
9、将置换后的R-32和本轮循环中刚开始拆分出来的L-32进行异或操作,将结果作为下一轮循环中的R-32。
// 异或操作后的结果为:
0010 1000 0011 1111 0011 0101 0111 0101 // 作为下一轮循环中的R-32
如果已经是最后一轮循环,则需要将L-32和R-32 拼接成为64位的二进制字符串。再根据末置换表(如下图)进行一轮末置换操作,最终得到加密之后的64位二进制字符串。
// 拼接结果为:
1 1 0 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 1 1 0 0 1
0 1 0 1 0 1 0 1
1 1 1 1 0 1 1 1
0 0 1 1 1 1 1 0
1 0 1 0 1 1 0 0
0 0 1 0 0 0 0 0
末置换表:
// 置换后结果为:
1 1 0 1 0 1 0 1
1 1 1 0 0 0 0 0
1 1 1 0 1 0 0 1
0 1 1 0 1 1 0 0
1 1 1 0 0 1 0 1
1 0 1 0 1 0 1 0
1 1 0 0 0 0 0 1
1 1 0 0 1 1 0 0
以上,就完成了DES加密算法中单轮循环的加密操作。共需要进行相同操作16轮。最后,将每64位二进制片段经过加密以后的密文都拼接起来,得到一个很长的二进制字符串(如下图),这就是原始明文加密以后输出的二进制密文。
// 所有明文片段经过16轮加密后拼接成的结果为:
11010101111000001110100101101100111001011010101011000001110011000011001110000011010101011010011100110110100101110000011110101011
最后,再将该二进制字符串换算成十六进制的格式输出,就是我们最终看到的DES加密后的结果:
// 将上述二进制进行十六进制的转换,最终结果为:
d5e0e96ce5aac1cc338355a7369707ab
解密
解密时,因为已知密钥和加密过程,所以只需先将十六进制的结果转换成二进制字符串,再把该二进制字符串分成每64位一组的片段,再进行加密过程的逆向操作即可得到该片段对应的明文片段。然后通过上文中提到的明文补位的解密去位算法,将每个明文片段中多余的内容去掉,得到初始传入的明文内容片段。最后再将所有明文片段拼接起来,得到初始明文。以上就是DES加密过程的全部内容了。