第二题-题目要求
如果16轮使用的子密钥K16=K1,K15=K2,…,K9=K8,
则加密所用的子密钥与解密所用的子密钥相同,
对一个明文X加密两次,得到的还是明文X.
弱密钥的定义:若k使得加密函数与解密函数一致,则称k为弱密钥.
证明下列密钥为弱密钥(偶校验:就是让原有数据序列中(包括你要加上的一位)1的个数为偶数):
0x00000000000000 2) 0x1E1E1E1E 0F0F0F0F
0x E1E1E1E1F0F0F0F0 4) 0xFFFFFFFFFFFFFF
0x00000000000000
由于该密钥的所有位均为0,因此在经过PC-1、左右两部分的循环左亦或是PC-2后,生成的16个子密钥每一位依然为0,因此显然$k_1=k_2=…k_{16}$,因此可以得出结论,该密钥为弱密钥
0x1E1E1E1E 0F0F0F0F
我们将其进行二进制转换后可以得到64位密钥:0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
我们可以利用代码将64位密钥进行PC-1置换,python代码如下:
#PC-1 # 获取用户输入的数字串 arr = input("请输入一串数字,以空格分隔:") arr = arr.split() # 将数字串转换为整数列表 arr = [int(x) for x in arr] # 定义规定的顺序 order =(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) # 按照规定顺序对数字列表进行重排 new_arr = [arr[i-1] for i in order] # 输出重排后的数字列表 print(new_arr)
可以得到56位密钥:0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
我们不难发现前28位密钥都为0,后28位密钥都为1,因此无论如何对前后两段密钥如何循环左移,其左右两部分都保持不变:$C_i=00000…0$,$D_i=11111…1$
随后我们进行PC-2置换,由于PC-2替换表的替换方式在16轮中保持不变,因此可知$k_1=k_2=…k_{16}$,因此可以得出结论,该密钥为弱密钥
0x E1E1E1E1F0F0F0F0
我们将其进行二进制转换后可以得到64位密钥:1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
我们同样里用代码将其进行PC-1转换可得到56位密钥:1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
我们不难发现前28位密钥都为1,后28位密钥都为0,因此无论如何对前后两段密钥如何循环左移,其左右两部分都保持不变:$C_i=11111…1$,$D_i=00000…0$
随后我们进行PC-2置换,由于PC-2替换表的替换方式在16轮中保持不变,因此可知$k_1=k_2=…k_{16}$,因此可以得出结论,该密钥为弱密钥
0xFFFFFFFFFFFFFF
由于该密钥的所有位均为1,因此其在经过PC-1、左右两部分的循环左亦或是PC-2后,生成的16个子密钥每一位依然为0,因此显然$k_1=k_2=…k_{16}$,因此可以得出结论,该密钥为弱密钥
第三题-题目要求
DES的密钥编排:
1)统计连续两轮的子密钥有多少密钥比特不相同?
2)统计连续两轮的子密钥是否覆盖初始密钥的56比特?
首先我们来统计连续两轮子密钥有多少密钥比特不同,我们利用PPT中给到的DES密钥编排64转48直接选取表可以编写一个省略生成过程的简易DES密钥编排生成代码,其python代码如下:
import random def compare_lists(list1, list2): """比较两个列表中同一位置上不同元素的个数""" count = 0 for i in range(len(list1)): if list1[i] != list2[i]: count += 1 return count #DES密钥编排算法生成子密钥直接轮表 table1 = [10,51,34,60,49,17,33,57,2,9,19,42,3,35,26,25,44,58,59,1,36,27,18,41,22,28,39,54,37,4,47,30,5,53,23,29,61,21,38,63,15,20,45,14,13,62,55,31] table2 = [2,43,26,52,41,9,25,49,59,1,11,34,60,27,18,17,36,50,51,58,57,19,10,33,14,20,31,46,29,63,39,22,28,45,15,21,53,13,30,55,7,12,37,6,5,54,47,23] table3 = [51,27,10,36,25,58,9,33,43,50,60,18,44,11,2,1,49,34,35,42,41,3,59,17,61,4,15,30,13,47,23,6,12,29,62,5,37,28,14,39,54,63,21,53,20,38,31,7] table4 = [35,11,59,49,9,42,58,17,27,34,44,2,57,60,51,50,33,18,19,26,25,52,43,1,45,55,62,14,28,31,7,53,63,13,46,20,21,12,61,23,38,47,5,37,4,22,15,54] table5 = [19,60,43,33,58,26,42,1,11,18,57,51,41,44,35,34,17,2,3,10,9,36,27,50,29,39,46,61,12,15,54,37,47,28,30,4,5,63,45,7,22,31,20,21,55,6,62,38] table6 = [3,44,27,17,42,10,26,50,60,2,41,35,25,57,19,18,1,51,52,59,58,49,11,34,13,23,30,45,63,62,38,21,31,12,14,55,20,47,29,54,6,15,4,5,39,53,46,22] table7 = [52,57,11,1,26,59,10,34,44,51,25,19,9,41,3,2,50,35,36,43,42,33,60,18,28,7,14,29,47,46,22,5,15,63,61,39,4,31,13,38,53,62,55,20,23,37,30,6] table8 = [36,41,60,50,10,43,59,18,57,35,9,3,58,25,52,51,34,19,49,27,26,17,44,2,12,54,61,13,31,30,6,20,62,47,45,23,55,15,28,22,37,46,39,4,7,21,14,53] table9 = [57,33,52,42,2,35,51,10,49,27,1,60,50,17,44,43,26,11,41,19,18,9,36,59,4,46,53,55,23,22,61,12,54,39,37,15,47,7,20,14,29,38,31,63,62,13,6,45] table10= [41,17,36,26,51,19,35,59,33,11,50,44,34,1,57,27,10,60,25,3,2,58,49,43,55,30,37,20,7,6,45,63,38,23,21,62,31,34,4,61,13,22,15,47,46,28,53,29] table11= [25,1,49,10,35,3,19,43,17,60,34,57,18,50,41,11,59,44,9,52,51,42,33,27,39,14,21,4,54,53,29,47,22,7,5,46,15,38,55,45,28,6,62,31,30,12,37,13] table12= [9,50,33,59,19,52,3,27,1,44,18,41,2,34,25,60,43,57,58,36,35,26,17,11,23,61,5,55,38,37,13,31,6,54,20,30,62,22,39,29,12,53,46,15,14,63,21,28] table13= [58,34,17,43,3,36,52,11,50,57,2,35,51,18,9,44,27,41,42,49,19,10,1,60,7,45,20,39,22,21,28,15,53,38,4,14,46,6,23,13,63,37,30,62,61,47,5,12] table14= [42,18,1,27,52,49,36,60,34,41,51,9,35,2,58,57,11,25,26,33,3,59,50,44,54,29,4,23,6,5,12,62,37,22,55,61,30,53,7,28,47,21,14,46,45,31,20,63] table15= [26,2,50,11,36,33,49,44,18,25,35,58,19,51,42,41,60,9,10,17,52,43,34,57,38,13,55,7,53,20,63,46,21,6,39,45,14,37,54,12,31,5,61,30,29,15,4,47] table16= [18,59,42,3,57,25,41,36,10,17,27,50,11,43,34,33,52,1,2,9,44,35,26,49,30,5,47,62,45,12,55,38,13,61,31,37,6,29,46,4,23,28,53,22,21,7,63,39] #1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #arr = input("请输入一串数字,以空格分隔:") #arr = arr.split() # 将数字串转换为整数列表 #arr = [int(x) for x in arr] # 随机生成一个只包含0和1的64位列表 arr= [random.randint(0, 1) for _ in range(64)] print("本次随机密钥密钥:",arr) print("以下为16轮子密钥:") arr1 =arr new_arr1 = [arr1[i-1] for i in table1] print(new_arr1) arr2 =arr new_arr2 = [arr2[i-1] for i in table2] print(new_arr2) count1 = compare_lists(new_arr1, new_arr2) print(f"连续两轮的子密钥有{count1}密钥比特不相同") arr3 =arr new_arr3 = [arr3[i-1] for i in table3] print(new_arr3) count2 = compare_lists(new_arr2, new_arr3) print(f"连续两轮的子密钥有{count2}密钥比特不相同") arr4 =arr new_arr4 = [arr4[i-1] for i in table4] print(new_arr4) count3 = compare_lists(new_arr3, new_arr4) print(f"连续两轮的子密钥有{count3}密钥比特不相同") arr5 =arr new_arr5 = [arr5[i-1] for i in table5] print(new_arr5) count4 = compare_lists(new_arr4, new_arr5) print(f"连续两轮的子密钥有{count4}密钥比特不相同") arr6 =arr new_arr6 = [arr6[i-1] for i in table6] print(new_arr6) count5 = compare_lists(new_arr5, new_arr6) print(f"连续两轮的子密钥有{count5}密钥比特不相同") arr7 =arr new_arr7 = [arr7[i-1] for i in table7] print(new_arr7) count6 = compare_lists(new_arr6, new_arr7) print(f"连续两轮的子密钥有{count6}密钥比特不相同") arr8 =arr new_arr8= [arr8[i-1] for i in table8] print(new_arr8) count7 = compare_lists(new_arr7, new_arr8) print(f"连续两轮的子密钥有{count7}密钥比特不相同") arr9 =arr new_arr9 = [arr9[i-1] for i in table9] print(new_arr9) count8 = compare_lists(new_arr8, new_arr9) print(f"连续两轮的子密钥有{count8}密钥比特不相同") arr10 =arr new_arr10 = [arr10[i-1] for i in table10] print(new_arr10) count9 = compare_lists(new_arr9, new_arr10) print(f"连续两轮的子密钥有{count9}密钥比特不相同") arr11 =arr new_arr11 = [arr11[i-1] for i in table11] print(new_arr11) count10 = compare_lists(new_arr10, new_arr11) print(f"连续两轮的子密钥有{count10}密钥比特不相同") arr12 =arr new_arr12 = [arr12[i-1] for i in table12] print(new_arr12) count11 = compare_lists(new_arr11, new_arr12) print(f"连续两轮的子密钥有{count11}密钥比特不相同") arr13 =arr new_arr13 = [arr13[i-1] for i in table13] print(new_arr13) count12 = compare_lists(new_arr12, new_arr13) print(f"连续两轮的子密钥有{count12}密钥比特不相同") arr14 =arr new_arr14 = [arr14[i-1] for i in table14] print(new_arr14) count13 = compare_lists(new_arr13, new_arr14) print(f"连续两轮的子密钥有{count13}密钥比特不相同") arr15 =arr new_arr15 = [arr15[i-1] for i in table15] print(new_arr15) count14 = compare_lists(new_arr14, new_arr15) print(f"连续两轮的子密钥有{count14}密钥比特不相同") arr16 =arr new_arr16 = [arr16[i-1] for i in table16] print(new_arr16) count15 = compare_lists(new_arr15, new_arr16) print(f"连续两轮的子密钥有{count15}密钥比特不相同") aver = (count1+count2+count3+count4+count5+count6+count7+count8+count9+count10+count11+count12+count13+count14+count15)/15 print(f"平均连续两轮的子密钥有{aver}密钥比特不相同")
通过这段代码,我们可以将随机生成的64 bit密钥在输出其16个子密钥的同时计算连续两轮的子密钥的密钥比特差异值的平均值,以下为一个输出实例:
本次随机密钥密钥: [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1]
以下为16轮子密钥:
[1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0]
[1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0]
连续两轮的子密钥有26密钥比特不相同
[0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]
连续两轮的子密钥有25密钥比特不相同
[0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0]
连续两轮的子密钥有24密钥比特不相同
[0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0]
连续两轮的子密钥有25密钥比特不相同
[0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1]
连续两轮的子密钥有25密钥比特不相同
[0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1]
连续两轮的子密钥有27密钥比特不相同
[1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
连续两轮的子密钥有27密钥比特不相同
[0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1]
连续两轮的子密钥有26密钥比特不相同
[1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0]
连续两轮的子密钥有25密钥比特不相同
[0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1]
连续两轮的子密钥有27密钥比特不相同
[1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]
连续两轮的子密钥有25密钥比特不相同
[1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]
连续两轮的子密钥有25密钥比特不相同
[1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1]
连续两轮的子密钥有26密钥比特不相同
[0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0]
连续两轮的子密钥有25密钥比特不相同
[1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0]
连续两轮的子密钥有25密钥比特不相同
平均连续两轮的子密钥有==25.533333333333335==密钥比特不相同我们在此基础上添加循环,进行十万次实验,统计出连续两轮的子密钥的密钥比特差异值的平均值为23.990703333333055
因此我们大致能够得出这样的结论:连续两轮的子密钥大约有多少23~24位密钥比特不相同
接下来我们来统计连续两轮的子密钥是否覆盖初始密钥的56比特, 首先我们来确定子密钥覆盖初始密钥的定义:当连续两轮的子密钥中包含了初始密钥中的全部或大部分信息时,我们称之为“子密钥覆盖初始密钥”
那我们将上面的子密钥生成代码稍作改动,统计连续两轮的子密钥对于初始密钥的56比特的覆盖率
同样经过十万次计算,我们能够得到平均连续两轮子密钥能够覆盖20.8861251 bit位
因此我们可以大致得到这样的结论:连续两轮的子密钥还不能覆盖初始密钥的56比特
另外:附上DES密钥编排的完整过程代码:
#include<stdio.h>
int subSecretKey[17][48];//16轮的子密钥1-16
int leftSecretKey[28]={1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};//进行第一轮置换后的左边秘密钥
int rightSecretKey[28]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};//进行第一轮置换后的右边秘密钥
int subLeftSecretKey[24];
int subRightSecretKey[24];
int s,i,m;
//为了数组表示方便,将置换选择2中的位置全部减小1
int LP[24] ={13,16,10,23,0,4,2,27,14,5,20,9,22,18,11,3,25,7,15,6,26,19,12,1};
//主函数
int RP[24] ={40,51,30,36,46,54,29,39,50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31};
int main()
{
int i,j,t;
//16轮的子密钥生成
for(i=1; i<=16;i++){
if(i==1|| i==2 ||i==9 ||i==16){
//循环左移一位
int tempLeft = leftSecretKey[0];
int tempRight = rightSecretKey[0];
for(j=0; j<27; j++){
leftSecretKey[j] = leftSecretKey[j+1];
rightSecretKey[j]= rightSecretKey[j+1];
}
leftSecretKey[27] = tempLeft;
rightSecretKey[27] = tempRight;
}
else {//循环左移两位
int tempLeft1 = leftSecretKey[0],
tempLeft2 = leftSecretKey[1];
int tempRight1 = rightSecretKey[0],
tempRight2 = rightSecretKey[1];
for(j=0; j<26; j++){
leftSecretKey[j] = leftSecretKey[j+2];
rightSecretKey[j]= rightSecretKey[j+2];
}
leftSecretKey[26]= tempLeft1;
leftSecretKey[27]= tempLeft2;
rightSecretKey[26]= tempRight1;
rightSecretKey[27]= tempRight2;
}
//置换,形成subLeftSecretKey[24 ],subRightSecretKey[24];
for(j=0; j<24; j++){
t=LP[j];
subLeftSecretKey[j] = leftSecretKey[t];
}
printf("\n");
for(j=0; j<24; j++){
t=RP[j];
//注意,由于开始分了两个数组输入,所以这里要减去前面的28位,才是正确的赋值
subRightSecretKey[j] = rightSecretKey[t-28];
}
//输出第i轮的子密钥
printf("第%d轮密钥为:",i);
for(s=0; s<48; s++){
if(s%4==0)
printf(" ");
if(s<24){
subSecretKey[i][s] = subLeftSecretKey[s];
printf("%d",subSecretKey[i][s]);
}
else{
subSecretKey[i][s] = subRightSecretKey[s-24];
printf("%d",subSecretKey[i][s]);
}
}
}
return 0;
}