实验目的
(1)理解常规密钥密码体制的特点。
(2)理解DES算法的实现过程。
(3)通过使用DES 算法对实验数据进行加密和解密。
实验环境
Microsoft Visual Studio C语言
实验原理
DES算法的入口参数:Key、Data、Mode。
Key为8个字节共64位,是DES算法的工作秘钥;
Data也为8个字节64位,是要被加密或解密的数据;
Mode为DES的工作方式,有两种:加密或解密。
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。
使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。
图 1 加密过程
图 2 解密过程
实验步骤及结果
1、加密
DES加密算法分为两个部分,一部分对密钥进行处理,一部分对明文进行处理。举例进行说明:
64位明文:M=00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111
64位密钥:K=00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000
(1)密钥
A.置换选择
置换选择1(PC_1)87矩阵:
在密钥当中,前八位00110001,第8位的1是奇偶校验位
这个表有两个作用,一是去掉8个奇偶校验位,二是其他位打乱重排,即得到的56位密钥(64-8)中第1位的数是原来64位的第57位的数,第2位的数是原来的第49位的数,以此类推。
经过上面的变换我们得到56位的密钥:K(56)=0000000 0000000 0011111 1111111 0110011 0011110 001000 00001111
再将前28位存储到C0,后28位存储到D0,即:
C0(28)=0000000 0000000 0011111 1111111
D0(28)=0110011 0011110 001000 00001111
B.循环左移
为了得到16个子密钥,我们需要有16对C和D。其中C1为C0循环左移得到,D1为D0循环左移得到,C2为C1循环左移得到,D2为D1循环左移得到,以此类推。循环左移1位的意思是把第一位保留下来,其他位左移,再将保留的第一位填到最后空出来的1位。循环左移的位数如下表所示:
最终,得到结果:
第1轮:C1=0000000 0000000 0111111 1111110
D1=1100110 0111100 0100000 0011110
第2轮:C2=0000000 0000000 1111111 1111100
D2=1001100 1111000 1000000 0111101
第16轮:C16=0000000 0000000 0011111 1111111
D16=0110011 0011110 0010000 0001111
左移完成后,将每对拼接起来构成56位的密钥
K1(56)=0000000 0000000 0111111 1111110 1100110 0111100 0100000 0011110
图 4 DES中计算子密钥的过程
接下来进行第二次置换,置换选择2(PC_2)68矩阵:
将56位变为48位,和PC_1原理一样,最终得到16个子密钥:
(2)明文
A. IP置换
IP置换表(IP)88:
将明文打乱顺序,得到M_IP(64)=00000000 11111111 11110000 10101010 00000000 11111111 00000000 11001100
再将其分为两部分L0、R0
L0(32)=00000000 11111111 11110000 10101010
R0(32)=00000000 11111111 00000000 11001100
接下来,从L0R0开始推L1R1,一共循环16次,推出L1-L16,根据以下规则:Ln=R(n-1);
Rn=L(n-1)异或P( S ( ( E ( R(n-1) ) 异或 Kn ) ) );
B. L16R16的运算
拓展置换:为了得到R1,首先执行最里面的E(R0)
选择运算/拓展置换(E)86:
将32位的R0拓展到48位,R0(48)=00000000 00010111 11111110 10000000 00010110 01011000
接下来进行E(R0)异或K1(48)=01010000 00111011 01010010 11010111 00111100 10011010
S盒:接下来进行 S(E(R0)异或K1(48))
代替函数S盒(S_box):
将上一步的结果分为8个6位的数据块:
1:010100 2:000011 3:101101 4:010010
5:110101 6:110011 7:110010 8:011010
对第1块处理,将6位中的第1位和第6位组成一个二进制数00,转为十进制数X=02+0=0。再将中间四位1010组成二进制数,转为十进制Y=18+04+12+01=10 。X作为行数,Y作为列数,第几块就去找第几盒,那这个块的结果就是S1的0行10列,即S_box[0][0][10],结果为6,将6转为二进制0110 。再对其余7块处理完成后,可以得到48=32位的结果:S(E(R0)异或K1(48))(32)=01101101 10000010 00001110 11110000
P置换:再进行P(S(E(R0)异或K1(48)))
置换运算(P)8*4:
与置换选择相同,进行置换后可以得到结果:P(S(E(R0)异或K1(48))(32))(32)=00010010 01111000 11000111 00011001
最后将这个结果和L0进行异或操作:
R1(32)=00010010 10000111 00110111 10110011
L1(32)=R0=00000000 11111111 00000000 11001100
按照拓展置换、S置换、P置换的顺序退出来L16和R16:
我们需要的就是L16和R16,将它们按R16L16的顺序拼接在一起组成64位数据。(64)1101010000010110100010101010000100110011111101101010110101000101
C.IP逆置换
按此表对上步结果进行最后的置换,得到最终的密文:C(64)=10001011 10110100 01111010 00001100 11110000 10101001 01100010 01101101
2、解密
解密的过程跟加密的过程一样,就是把明文换成密文,密钥不变,对密文进行操作,IP置换,获得L0R0,在进行16次递推运算时有不同,密文解密的运算规则是:Ln=R(n-1);Rn=L(n-1)异或P( S ( ( E ( R(n-1) ) 异或 K(16-n+1) ) ) );相比于加密过程明文在获取R1时,使用的是子密钥K1,解密时密文在获取R1时,使用的是子密钥K16,获取R2使用K15,然后依次进行S盒、P置换、IP逆置换可以得到明文。
解密后得到明文如下,对比结果正确。
实验总结
1、实验过程中遇到的问题及解决办法;
(1)对于算法的原理和具体的实现不是很熟练,查阅相关资料对过程有了很详细的理解,包括源代码中所需的具体定义及函数。
(2)将读到的字符串写入数组时,使用gets语句会报错,需将gets改为gets_s。
2、设计及调试过程中的心得体会。
通过完成这次实验报告,我明白了当开始完成一项任务时,难免不知从何下手,所以可以通过查阅相关知识,明白具体的实验步骤,从而可以通过代码一步步实现出来,遇到困难解决困难,动手实践后对DES算法有更深入的理解,对于网络安全和加密算法有了更深厚的兴趣,知识是需要不断回顾与补充的,这次实验还将C语言的语句进行了回顾。