DES加密解密算法之python实现版(图文并茂)

Delicia ·
更新时间:2024-09-20
· 971 次阅读

一、DSE算法背景介绍

1. DES的采用
1979年,美国银行协会批准使用
1980年,美国国家标准局(ANSI)赞同DES作为私人使用的标准,称之为DEA(ANSI X.392)
1983年,国际化标准组织ISO赞同DES作为国际标准,称之为DEA-1
该标准规定每五年审查一次,计划十年后采用新标准
最近的一次评估是在1994年1月,已决定1998年12月以后,DES将不再作为联邦加密标准。

2.DES算法特点

1) 分组加密算法:

以64位为分组。64位一组的明文从算法一端输入,64位密文从另一端输出。

2) 对称算法:

加密和解密用同一密钥。

3) 有效密钥长度为56位。

密钥通常表示为64位数,但每个第8位用作奇偶校验,可以忽略。输入的64bit秘钥只有56bit作为有效位

二、DES算法描述

1、DES算法加密流程的文字描述

DES对64位的明文分组进行操作。通过一个初始置换,将明文分组分成左半部分和右半部分,各32位长。然后进行16轮完全相同的运算,这些运算被称为函数f,在运算过程中数据与密钥结合。经过16轮后,左、右半部分合在一起,经过一个末置换(初始置换的逆置换),这样该算法就完成了。

二、DES算法加密流程的图形描述


                              图一

图二

三、具体参数解释

1、IP置换和IP逆置换

IP置换作用于进行16轮f函数作用之前,IP逆置换作用于16轮f函数作用之后。IP置换和IP逆置换表如下图所示:

图三

该表的含义解释:例如IP置换表中的第一行第一列的数值为58,就代表将明文的第58位替换到第一位,例如明文初始的第58位是1,第1位是0,第39位是0,根据上表替换后的64位待加密文本为:第一位是1,第58位是0。之后提到的置换表也是这个意思。

2、f函数

经过初始置换后,进行16轮完全相同的运算。这些运算被称为f,在运算过程中数据与密钥结合。f函数作用于每轮的key值和每轮的待加密文本的右半部分,即Ki,Ri

f函数作用于每轮的key值和每轮的待加密文本的右半部分,即Ki,Ri


                                                             图四

函数¦的输出经过一个异或运算,和左半部分结合,其结果成为新的右半部分,原来的右半部分成为新的左半部分。


                                                                                  图五

3、扩展置换,扩展置换将32位的R部分,扩展为48位

扩展表如图所示:


                                                  图六

4、S盒替换,S盒替换将扩展替换后与ki(第i轮KEY值)异或后的结果压缩为32位,每6位与一个S盒运算,运算后压缩为4位,共有八个S盒,分为S1,S2......S8。具体如下图所示


                                                                                              图七

S盒介绍,以第六个S盒,S6为例


                                                                                                                                       图八

设入的六位为b1,b2,b3,b4,b5,b6,b1、b6位组合得到列号,b2,b3,b4,b5组合得到行号。具体实现看底下的代码。确定行号和列好后将6位替换为4位数据,数据段具体值即为行列相交处的值,例如3行4列即为5,5的二进制码位1001,将原来的6位替换为4位即1001

4、P盒替换

P盒替换将S盒替换之后的结果进行一次位置替换,替换表如图所示:

                                                                                                  图九

5 最后讲一下重头戏——16轮秘钥生成

先上个图

                                                                                                    图10

图中的置换选择1和置换选择2跟之前将的置换选择原理是一样的,在代码中你能看到置换表

这里也给出来吧


                                                         图11

C0,D0指的是将56位(注位都是指的bit)秘钥分为左右两部分,C0代表左半部分,D0是右半部分。循环左移指的是将bit位循环左移,移除的位补到末尾,l例如100010循环左移一位之后位000101

每轮秘钥生成的时候循环左移的次数都不一样,具体如下表


                                                                                   图12

四、以上都是文字加图表描述,下面直接上代码,代码我都加了详细的备注,大家结合上面的说明一定能读懂滴。有点长,大家细心看

#writter:liuyang@BUAASoftwareDepartment #date:2014/05/14 #function:DEC加密、解密算法 #contact me:734056968@qq.com #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置换表 _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] #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 ] #压缩置换表1,不考虑每字节的第8位,将64位密钥减至56位。然后进行一次密钥置换。 yasuo1_table=[ 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 yasuo2_table=[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 ] #用于对数据进行扩展置换,将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 ] #将字符转换为对应的Unicode码,中文用2个字节表示 def char2unicode_ascii(intext,length):     outtext=[]     for i in range(length):         outtext.append(ord(intext[i]))     return outtext #将Unicode码转为bit     def unicode2bit(intext,length):     outbit=[]     for i in range(length*16):         outbit.append((intext[int(i/16)]>>(i%16))&1)#一次左移一bit     return outbit #将8位ASCII码转为bit     def byte2bit(inchar,length):     outbit=[]     for i in range(length*8):         outbit.append((inchar[int(i/8)]>>(i%8))&1)#一次左移一bit     return outbit #将bit转为Unicode码 def bit2unicode(inbit,length):     out=[]     temp=0     for i in range(length):         temp=temp|(inbit[i]<<(i%16))         if i%16==15:                         out.append(temp)             temp=0     return out #将bit转为ascii 码 def bit2byte(inbit,length):     out=[]     temp=0     for i in range(length):         temp=temp|(inbit[i]<<(i%8))         if i%8==7:                         out.append(temp)             temp=0     return out #将unicode码转为字符(中文或英文) def unicode2char(inbyte,length):     out=""     for i in range(length):         out=out+chr(inbyte[i])     return out #生成每一轮的key def createKeys(inkeys):     keyResult=[]     asciikey=char2unicode_ascii(inkeys,len(inkeys))     keyinit=byte2bit(asciikey,len(asciikey)) #    print("keyinit=",end='') #    print(keyinit)     #初始化列表key0,key1     key0=[0 for i in range(56)]     key1=[0 for i in range(48)]     #进行密码压缩置换1,将64位密码压缩为56位     for i in range(56):         key0[i]=keyinit[yasuo1_table[i]-1]              #进行16轮的密码生成             for i in range(16):         #---------确定左移的次数----------         if (i==0 or i==1 or i==8 or i==15):             moveStep=1         else:             moveStep=2         #------------------------------                      #--------分两部分,每28bit位一部分,进行循环左移------------             for j in range(moveStep):             for k in range(8):                 temp=key0[k*7]                 for m in range(7*k,7*k+6):                     key0[m]=key0[m+1]                 key0[k*7+6]=temp             temp=key0[0]             for k in range(27):                 key0[k]=key0[k+1]             key0[27]=temp             temp=key0[28]             for k in  range(28,55):                 key0[k]=key0[k+1]             key0[55]=temp         #-----------------------------------------------------         #------------对56位密钥进行压缩置换,压缩为48位-------------         for k in range(48):             key1[k]=key0[yasuo2_table[k]-1]              keyResult.extend(key1)                  #------------------------------------------------------              return keyResult def DES(text,key,optionType):     keyResult=createKeys(key)     finalTextOfBit=[0 for i in range(64)]     finalTextOfUnicode=[0 for i in range(4)] #    print(keyResult)                   if optionType==0:#选择的操作类型为加密                  tempText=[0 for i in range(64)]#用于临时盛放IP逆置换之前,将L部分和R部分合并成64位的结果         extendR=[0 for i in range(48)]#用于盛放R部分的扩展结果         unicodeText=char2unicode_ascii(text,len(text)) #        print(unicodeText)         bitText=unicode2bit(unicodeText,len(unicodeText)) #        print(bitText)                  initTrans=[0 for i in range(64)]#初始化,用于存放IP置换后的结果                  #------------------进行初始IP置换---------------         for i in range(64):             initTrans[i]=bitText[IP_table[i]-1]         #将64位明文分为左右两部分         L=[initTrans[i] for i in range(32)]         R=[initTrans[i] for i in range(32,64)]                           #开始进行16轮运算                       for i in range(16):             tempR=R #用于临时盛放R                          #-----------进行扩展,将32位扩展为48位--------             for j in range(48):                 extendR[j]=R[extend_table[j]-1]  #           print(len(keyResult))                 keyi=[keyResult[j] for j in range(i*48,i*48+48)]             #----------与key值进行异或运算----------------             XORResult=[0 for j in range(48)]             for j in range(48):                 if keyi[j]!=extendR[j]:                     XORResult[j]=1                          SResult=[0 for k in range(32)]              #---------开始进行S盒替换-------------------                       for k in range(8):                 row=XORResult[k*6]*2+XORResult[k*6+5]                 column=XORResult[k*6+1]*8+XORResult[k*6+2]*4+XORResult[k*6+3]*2+XORResult[k*6+4]                 temp=S[k][row*16+column]                 for m in range(4):                     SResult[k*4+m]=(temp>>m)&1              #-----------------------------------------             PResult=[0 for k in range(32)]             #--------------开始进行P盒置换----------------             for k in range(32):                 PResult[k]=SResult[P_table[k]-1]             #------------------------------------------             #--------------与L部分的数据进行异或------------             XORWithL=[0 for k in range(32)]             for k in range(32):                 if L[k]!=PResult[k]:                     XORWithL[k]=1             #----------------------------------------------             #-------------将临时保存的R部分值,即tempR复制给L------             L=tempR             R=XORWithL                      #----交换左右两部分------         L,R=R,L                  #-----合并为一部分         tempText=L         tempText.extend(R)         #-----------IP逆置换--------         for k in range(64):             finalTextOfBit[k]=tempText[_IP_table[k]-1]         finalTextOfUnicode=bit2byte(finalTextOfBit,len(finalTextOfBit)) #        print(finalTextOfUnicode)         finalTextOfChar=unicode2char(finalTextOfUnicode,len(finalTextOfUnicode)) #        print(finalTextOfChar)         return finalTextOfChar     else:#选择的操作类型为解密         tempText=[0 for i in range(64)]#用于临时盛放IP逆置换之前,将L部分和R部分合并成64位的结果         extendR=[0 for i in range(48)]#用于盛放R部分的扩展结果         unicodeText=char2unicode_ascii(text,len(text)) #        print(unicodeText)         bitText=byte2bit(unicodeText,len(unicodeText)) #        print(bitText)                  initTrans=[0 for i in range(64)]#初始化,用于存放IP置换后的结果                  #------------------进行初始IP置换---------------         for i in range(64):             initTrans[i]=bitText[IP_table[i]-1]         #将64位明文分为左右两部分         L=[initTrans[i] for i in range(32)]         R=[initTrans[i] for i in range(32,64)]                  #-----------------开始16轮的循环-----------------         for i in range(15,-1,-1):             tempR=R #用于临时盛放R                          #-----------进行扩展,将32位扩展为48位--------             for j in range(48):                 extendR[j]=R[extend_table[j]-1]                              keyi=[keyResult[j] for j in range(i*48,i*48+48)]             #----------与key值进行异或运算----------------             XORResult=[0 for j in range(48)]             for j in range(48):                 if keyi[j]!=extendR[j]:                     XORResult[j]=1                          SResult=[0 for k in range(32)]              #---------开始进行S盒替换-------------------                       for k in range(8):                 row=XORResult[k*6]*2+XORResult[k*6+5]                 column=XORResult[k*6+1]*8+XORResult[k*6+2]*4+XORResult[k*6+3]*2+XORResult[k*6+4]                 temp=S[k][row*16+column]                 for m in range(4):                     SResult[k*4+m]=(temp>>m)&1              #-----------------------------------------             PResult=[0 for k in range(32)]             #--------------开始进行P盒置换----------------             for k in range(32):                 PResult[k]=SResult[P_table[k]-1]             #------------------------------------------             #--------------与L部分的数据进行异或------------             XORWithL=[0 for k in range(32)]             for k in range(32):                 if L[k]!=PResult[k]:                     XORWithL[k]=1             #----------------------------------------------             #-------------将临时保存的R部分值,即tempR复制给L------             L=tempR             R=XORWithL                      #----交换左右两部分------         L,R=R,L                  #-----合并为一部分         tempText=L         tempText.extend(R)         #-----------IP逆置换--------         for k in range(64):             finalTextOfBit[k]=tempText[_IP_table[k]-1]         finalTextOfUnicode=bit2unicode(finalTextOfBit,len(finalTextOfBit)) #        print(finalTextOfUnicode)         finalTextOfChar=unicode2char(finalTextOfUnicode,len(finalTextOfUnicode)) #        print(finalTextOfChar)         return finalTextOfChar            def main():          text=input("请输入要操作的文本:  ")     print(" ".join(["输入的文本时",text]))     optionType=input("请选择是进行加密还是解密,加密输入0,解密输入1:  ")     while(not(optionType=='0' or optionType=='1')):         print("Wrong!!!选择的操作类型只能是0或者是1")         optionType=input("请选择是进行加密还是解密,加密输入0,解密输入1:  ")     length=len(text)     Result=""     if optionType=='0': #        f=open('D:\encyptText.txt','w')  #----------若输入文本的长度不是4的整数倍,即不是64字节的整数倍,用空格补全(此处为了加密中文,用的是unicode编码,即用16字节表示一个字符)-------         text=text+(length%4)*" "         length=len(text)         key=input("请输入8位加密密码: ")                  while(len(key)!=8):             print("wrong!!请输入8位密码")             key=input("请输入8位加密密码: ")                      print("加密后的文本:",end=" ")                     for i in range(int(length/4)):             tempText=[text[j] for j in range(i*4,i*4+4)]             Result="".join([Result,DES(tempText,key,int(optionType))]) #            f.write(Result)         print(Result)      if optionType=='1':  #----------若输入文本的长度不是8的整数倍,即不是64字节的整数倍,用空格补全(此处解密出来的密文用的是每8bit转换为一个ascii码,所以生成的八位表示的字符)------- #        text=text+(length%8)*" "         length=len(text)          key=input("请输入8位解密密码: ")         while(len(key)!=8):             print("wrong!!请输入8位密码")             key=input("请输入8位解密密码: ")                      print("解密后的文本:",end=" ")         for i in range(int(length/8)):             tempText=[text[j] for j in range(i*8,i*8+8)]             Result="".join([Result,DES(tempText,key,int(optionType))])         print(Result)

六、运行截图

图13

七、后记

1、要用于具体项目的话,要把编码格式弄清楚,看你项目中的编码格式是什么,unicode,utf-8,gdb等否则会出错

2、文本输入的时候不能有换行,如果需要换行加一下转换符,调一调

您可能感兴趣的文章:Python3对称加密算法AES、DES3实例详解python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序python3+PyQt5+Qt Designer实现扩展对话框python3+PyQt5+Qt Designer实现堆叠窗口部件详解Python 序列化Serialize 和 反序列化Deserializepython基于pyDes库实现des加密的方法深入解析Python中的descriptor描述器的作用及用法python实现DES加密解密方法实例详解Python Des加密解密如何实现软件注册码机器码



des加密 des 算法 Python

需要 登录 后方可回复, 如果你还没有账号请 注册新账号