des 算法
Des算法设计
这里使用python去实现des算法的实现,在代码中加深对des算法的理解,用代码去理解算法,确实会让整体逻辑变得更加清晰,所以,我感觉学习这类密码算法,最好有能力的都去实现一遍吧。
废话不多说,开干。
这里呢,我们首先去了解算法的原理,就可以很快的将算法分为三部分去看待
- 重点部分createKey模块,你需要在这个模块里面去将keylist这个列表去补充完成,因为后面的F运算,每一轮都是需要一个单独的子密钥的,所以第一步就是把全部的子密钥给生成好,密钥的生成逻辑其实本质也不是复杂的,就是64bit进去换成56bit,然后分成两组,分别进行一个移位操作,然后再将他们合并,最后进行一个48bit置换,就变成了一个key了。
# -*- coding = utf-8 -*- # @Time : 2021/9/23 14:06 # @Author : 刘卓文 # @File : createkey.py # @Software : PyCharm pc1=[ 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 ] #压缩置换表2,用于将循环左移和右移后的56bit密钥压缩为48bit pc2=[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 ] def bit48(lastKey): key1 = [0 for i in range(48)] for k in range(48): key1[k] = lastKey[pc2[k] - 1] return key1 #64>>64bit def displacement(tmp,step): movedTmp = tmp[step:] + tmp[:step] return movedTmp def createKey(text): keyResult = [] key0 =[0 for i in range(56)] key1 = [0 for i in range(48)] lastKey = [0 for i in range(48)] for i in range(56): key0[i] = text[pc1[i]-1] C = key0[0:28] D = key0[28:56] for i in range(16): if(i==0 or i==1 or i==8 or i==15): step = 1 else: step = 2 C = displacement(C,step) D = displacement(D,step) lastKey = C+D key1 = bit48(lastKey) keyResult.append(key1) return keyResult #改变的keyresult里面的值去了,实际的key1没有被改变
2.第二个重点部分当然是F轮函数的实现了,这也就是这个算法实现混沌性和扩散性的一个关键,其实本质也不难,总结下:就是32变成48bit,48bit和48bit密钥进行个异或操作,然后进入得到的结果进入个8个6进4出s盒子,然后得到32bit的数据,再把它扔到P盒子里面去进行个置换,这样的操作重复16轮,那么轮函数其实就完成了,实现起来其实也没那么复杂。就是把主要的几个模块写好,emm比如,XOR,Sbox这些。
# -*- coding = utf-8 -*- # @Time : 2021/9/23 13:58 # @Author : 刘卓文 # @File : F_function.py # @Software : PyCharm MaxTime = 16 # IP置换表 IP_table = [58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7] # 逆IP置换表 Inv_IP_table = [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] # S盒中的S1盒 S1 = [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] # S盒中的S2盒 S2 = [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] # S盒中的S3盒 S3 = [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] # S盒中的S4盒 S4 = [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] # S盒中的S5盒 S5 = [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] # S盒中的S6盒 S6 = [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] # S盒中的S7盒 S7 = [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] # S盒中的S8盒 S8 = [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] # S盒 S = [S1, S2, S3, S4, S5, S6, S7, S8] # 用于对数据进行扩展置换,将32bit数据扩展为48bit extend_table = [ 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] # P盒 P_table = [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] def IP(text,op): tmp = [0 for i in range(64)] if op == 0: for i in range(64): tmp[i] = text[IP_table[i]-1] return tmp if op == 1: for i in range(64): tmp[i] = text[Inv_IP_table[i]-1] return tmp def init2bit(num): a = [] for i in range(0, 4): a.insert(0, str(num % 2)) num = int(num / 2) return a def Extend48(text): extend = [0 for i in range(48)] for i in range(48): extend[i] = text[extend_table[i]-1] return extend def Sbox(text): sResult = [] for i in range(8): row = 2*int(text[6*i]) + int(text[6*i+5]) column = 8*int(text[6*i+1]) + 4*int(text[6*i+2]) + 2*int(text[6*i+3]) + int(text[6*i+4]) sNum = S[i][row*16+column] tmp = init2bit(sNum) for i in range(4): sResult.append(tmp[i]) return sResult def Pbox(text): pResult = [0 for i in range(32)] for i in range(32): pResult[i] = text[P_table[i]-1] return pResult def Xor(bit1,bit2): xResult = [0 for i in range(len(bit1))] for i in range(len(bit1)): xResult[i] = str(int(bit1[i]) ^ int(bit2[i])) return xResult
3.到这里就很简单了,你只需要拼积木一样,将上面的全部积木进行一个拼接,根据Des算法的总体流程去组织代码了
# -*- coding = utf-8 -*- # @Time : 2021/9/23 20:59 # @Author : 刘卓文 # @File : Des.py # @Software : PyCharm import F_function as F import createkey as ck import time from multiprocessing import Process def Hexbin(text): result = [] for i in range(len(text)): result.extend(F.init2bit(int(text[i],16))) return result #二进制比特串转十六进制 def bin2Hex(text): result = [] q = len(text)//4 for i in range(q): dec = int(text[4*i])*8 + int(text[4*i+1])*4 + int(text[4*i+2])*2 + int(text[4*i+3])*1 x = hex(dec)[2:].upper() result.extend(x) rs = ''.join(result) return rs def desEncryption(text, keyList): text1 = F.IP(text,0) L = text1[0:32] R = text1[32:64] for i in range(16): tmp = R tmp =F.Extend48(tmp) tmp = F.Xor(tmp,keyList[i]) tmp = F.Sbox(tmp) tmp = F.Pbox(tmp) tmp = F.Xor(tmp,L) L = R R = tmp #因为上面的tmp里面保存的就是r15,也就是l16,所以要进行交换 L, R = R, L ctext = L ctext.extend(R) ctext = F.IP(ctext,1) return bin2Hex(ctext) if __name__ == '__main__': plaintext = input("请输入用十六进制表示的明文:") key = input("请输入用十六进制表示的密钥:") start = time.perf_counter() ptext = Hexbin(plaintext) keybit = Hexbin(key) keyList = ck.createKey(keybit) print('输出的密文为:' + desEncryption(ptext,keyList)) end = time.perf_counter() print('Running time: %s Seconds' % (end - start))
总结下写完代码遇到的坑:
1.总体写完之后呢,果不其然的遇到了bug,再debug中发现居然creatkey模块写错了,直接第一步就gg,debug发现,keylist里面的内容全是错误的,这里我真的服了,如果你是直接向我一样,for循环里面去进行一个置换吗,然后将结果放入一个结果数组,那么这个结果数组会被上面的置换数组影响,鬼知道发生了什么,解决办法也不难,就是把置换进行一个封装,弄成函数就可以了,这波是真的奇怪。
2.就是p盒子写错了,那个return写在for里面了,纯属是眼睛瞎了。
再就是代码的优化层面做个简单的总结:
1. 首先16轮运算因为数据是单流向的,并且他们都属于cpu密集型运算,多线程的本质是解决IO密集型的那种运算形式,去利用cpu和IO并发执行的特点去节省时间成本呢,所以在这里使用多线程并发执行,并不能加快整个程序运行的速度,所以高并发的去实现16轮运算是不可取的。
2.但是如果我们要将des加密应用到实际的生活中,往往数据量是巨大的,那么这个时候将数据分组,然后利用多进程,使用电脑的多核心优势去进行算法的计算,就会将算法的运行速度提升核心数目个倍数,像这种cpu密集型的计算,多进程分组计算相对串行确实大大的提高了程序本来的效率
3.从算法本身进行一个优化,也就是从算法本身的流程去考量,
一:是从E盒层面去优化,直接从E盒的逻辑层面对数据进行一个扩展
二:是将s盒和p盒进行一个合并,合并成为sp盒子,
4.从硬件层面进行优化,通过流水线结构去实现逻辑的简化,在很长的组合路径的途中增加寄存器,减少逻辑级

浙公网安备 33010602011771号