Python實現DES

前言

密碼學作業之DES

簡介

DES全稱爲Data Encryption Standard,即數據加密標準,是一種使用密鑰加密的塊算法,1977年被美國聯邦政府的國家標準局確定爲聯邦資料處理標準(FIPS),並授權在非密級政府通信中使用,隨後該算法在國際上廣泛流傳開來。需要注意的是,在某些文獻中,作爲算法的DES稱爲數據加密算法(Data Encryption Algorithm,DEA),已與作爲標準的DES區分開來。

原理及步驟

初始置換
DES算法使用64位的密鑰key將64位的明文輸入塊變爲64位的密文輸出塊,並把輸出塊分爲L0、R0兩部分,每部分均爲32位。

加密處理–迭代過程

經過初始置換後,進行16輪完全相同的運算,在運算過程中數據與祕鑰結合。
函數f的輸出經過一個異或運算,和左半部分結合形成新的右半部分,原來的右半部分成爲新的左半部分
kbnSfI.png

F函數
F函數由四步運算構成:
祕鑰置換(Kn的生成,n=0~16);擴展置換;S-盒代替;P-盒置換

F函數–祕鑰置換–子密鑰生成*
DES算法由64位祕鑰產生16輪的48位子祕鑰。在每一輪的迭代過程中,使用不同的子祕鑰。

F函數–密鑰置換選擇1—PC-1
64位祕鑰降至56位祕鑰不是說將每個字節的第八位刪除,而是通過縮小選擇換位表1(置換選擇表1)的變換變成56位。

F函數–擴展置換E
通過擴展置換E,數據的右半部分Rn從32位擴展到48位。擴展置換改變了位的次序,重複了某些位。

F函數–S-盒代替
異或以後的結果作爲輸入塊進行S盒代替運算
功能是把48位數據變爲32位數據
代替運算由8個不同的代替盒(S盒)完成。每個S-盒有6位輸入,4位輸出。
所以48位的輸入塊被分成8個6位的分組,每一個分組對應一個S-盒代替操作。
經過S-盒代替,形成8個4位分組結果。

F函數-- P-盒置換
S-盒代替運算,每一盒得到4位,8盒共得到32位輸出。這32位輸出作爲P盒置換的輸入塊。

P盒置換將每一位輸入位映射到輸出位。任何一位都不能被映射兩次,也不能被略去。

經過P-盒置換的結果與最初64位分組的左半部分異或,然後左右兩部分交換,開始下一輪迭代。

逆置換
將初始置換進行16次的迭代,即進行16層的加密變換,這個運算過程我們暫時稱爲函數f。得到L16和R16,將此作爲輸入塊,進行逆置換得到最終的密文輸出塊。

DES解密

加密和解密可以使用相同的算法。加密和解密唯一不同的是祕鑰的次序是相反的。就是說如果每一輪的加密祕鑰分別是K1、K2、K3…K16,那麼解密祕鑰就是K16、K15、K14…K1。爲每一輪產生祕鑰的算法也是循環的。加密是祕鑰循環左移,解密是祕鑰循環右移。

合理性分析
DES是一個對稱密碼體制,加密和解密使用同一密鑰,有效的密鑰長度爲56位。DES是一個分組密碼算法,分組長度爲64位,明文和密文的長度相同。另外,DES採用了Feistel結構,具有加密與解密相識的特性。

安全性分析
DES算法具有極高安全性,到目前爲止,除了用窮舉搜索法對DES算法進行攻擊外,還沒有發現更有效的辦法。而56位長的密鑰的窮舉空間爲256,這意味着如果一臺計算機的速度是每一秒種檢測一百萬個密鑰,則它搜索完全部密鑰就需要將近2285年的時間,可見,這是難以實現的,當然,隨着科學技術的發展,當出現超高速計算機後,我們可考慮把DES密鑰的長度再增長一些,以此來達到更高的保密程度。
DES還存在以下的問題:
(1) 互補性(DES的最大弱點)
(2) 弱密鑰
(3) 迭代輪數
(4) 密鑰長度

Python完整代碼

按步驟,代碼較繁瑣

這個是完整的按照上面的步驟來的,比較複雜的代碼(看的同學的,我沒寫出來)。

#coding:utf-8
key = "this is a key"

Ip = [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_1= [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]

PC_1 = [57,49,41,33,25,17,9,1,58,40,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]

E = [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]

PC_2 = [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]

left_mov = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]

S = [[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],   #S1

    	 [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],	  #S2

    	 [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],	  #S3

    	 [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],	  #S4

    	 [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,	  #S5
     	  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],

    	 [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,	  #S6
     	  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],

	     [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,	  #S7
     	  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],

	     [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,	  #S8
     	  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]]

P = [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 init_IP(m1):		#IP初始置換,將明文轉化成64比特後置換
	mp = []
	for i in range(0,64):
		mp.append(m1[Ip[i]-1])
	return mp

def init_IP_1(m1):			#IP逆初始置換
	mp_1 = []
	for i in range(0,64):
		mp_1.append(m1[Ip_1[i]-1])
	return mp_1

def F(L,R,r):							#F()函數
	right = []
	for i in range(0,48):				#擴展置換E
		right.append(R[E[i]-1])
	a = []
	k=setKey(pKey(key),r)
	for i in range(0,48):				#密鑰加
		a.append(str((int(right[i])+int(k[i]))%2))
	s = ""
	for i in range(0,8):								#S盒代換
		b = a[:6]
		a = a[6:]                           #S盒代換
		h = int((b[0]+b[5]),2)
		l = int((b[1]+b[2]+b[3]+b[4]),2)
		s += str(bin(S[i][h*16+l])[2:]).zfill(4)
	p = []
	t = list(s)
	for i in range(0,32):								#置換運算P
		p.append(t[P[i]-1])
	return p

def pKey(k):		#密鑰置換,將密鑰從64位置換成56位
	str1 = ""
	for i in k:
		str1 += str(bin(ord(i))[2:]).zfill(8)
	list_t = list(str1)
	list_k = []
	for i in range(0,56):
		list_k.append(list_t[PC_1[i]-1])
	return list_k

def setKey(t,r):			#生成每一輪迭代的48位密鑰
	for i in range(0,r):
		ll = t[:28]
		lr = t[28:]
		ll = ll[left_mov[i]:]+ll[:left_mov[i]]
		lr = lr[left_mov[i]:]+lr[:left_mov[i]]
		t = ll+lr
	list_k = []
	for i in range(0,48):
		list_k.append(list_t[PC_2[i]-1])
	return list_k

def desEncrypt(m):
	print "Encrypt: "
	list_m = init_IP(m)
	L = list_m[:32]
	R = list_m[32:]
	for i in range(1,17):     	#16輪迭代
		list_p = F(L,R,i)
		temp = R
		x = ""
		for j in range(0,32):
		 	x += str((int(list_p[j])+int(L[j]))%2)
		R = list(x)
		L = temp
	c = init_IP_1(list(R+L))	
	print "".join(c)
	return "".join(c)

def desDecrypt(c):
	print "Decrypt:"
	list_c = init_IP(c)
	L = list_c[:32]
	R = list_c[32:] 
	for i in range(1,17):     	#16輪迭代
		list_p = F(L,R,17-i)
		temp = R
		x = ""
		for i in range(0,32):
		 	x += str((int(list_p[i])+int(L[i]))%2)
		R = list(x)
		L = temp
	list_m = init_IP_1(list(R+L))	
	m = ""
	for i in range(0,8):
		a = "".join(list_m[:8])
		m += chr(int(a,2))
		list_m = list_m[8:]
	print m
	return m

if __name__ == '__main__':
	m = "cumt2016"
	str1 = ""
	for i in m:
		str1 = str1+str(bin(ord(i))[2:]).zfill(8)
	list_t = list(str1)
	c = desEncrypt(list_t)
	desDecrypt(list(c))

速度快,佔內存小

這個是大神寫的,在網上看到的,不知道哪位大佬的。

from functools import partial  
  
class DES(object):  
    __ip = [  
        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,  
    ]  
    __ip1 = [  
        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,  
    ]  
    __e = [  
        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 = [  
        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,  
    ]  
    __s = [  
        [  
        0xe,0x4,0xd,0x1,0x2,0xf,0xb,0x8,0x3,0xa,0x6,0xc,0x5,0x9,0x0,0x7,  
        0x0,0xf,0x7,0x4,0xe,0x2,0xd,0x1,0xa,0x6,0xc,0xb,0x9,0x5,0x3,0x8,  
        0x4,0x1,0xe,0x8,0xd,0x6,0x2,0xb,0xf,0xc,0x9,0x7,0x3,0xa,0x5,0x0,  
        0xf,0xc,0x8,0x2,0x4,0x9,0x1,0x7,0x5,0xb,0x3,0xe,0xa,0x0,0x6,0xd,  
        ],  
        [  
        0xf,0x1,0x8,0xe,0x6,0xb,0x3,0x4,0x9,0x7,0x2,0xd,0xc,0x0,0x5,0xa,  
        0x3,0xd,0x4,0x7,0xf,0x2,0x8,0xe,0xc,0x0,0x1,0xa,0x6,0x9,0xb,0x5,  
        0x0,0xe,0x7,0xb,0xa,0x4,0xd,0x1,0x5,0x8,0xc,0x6,0x9,0x3,0x2,0xf,  
        0xd,0x8,0xa,0x1,0x3,0xf,0x4,0x2,0xb,0x6,0x7,0xc,0x0,0x5,0xe,0x9,  
        ],  
        [  
        0xa,0x0,0x9,0xe,0x6,0x3,0xf,0x5,0x1,0xd,0xc,0x7,0xb,0x4,0x2,0x8,  
        0xd,0x7,0x0,0x9,0x3,0x4,0x6,0xa,0x2,0x8,0x5,0xe,0xc,0xb,0xf,0x1,  
        0xd,0x6,0x4,0x9,0x8,0xf,0x3,0x0,0xb,0x1,0x2,0xc,0x5,0xa,0xe,0x7,  
        0x1,0xa,0xd,0x0,0x6,0x9,0x8,0x7,0x4,0xf,0xe,0x3,0xb,0x5,0x2,0xc,  
        ],  
        [  
        0x7,0xd,0xe,0x3,0x0,0x6,0x9,0xa,0x1,0x2,0x8,0x5,0xb,0xc,0x4,0xf,  
        0xd,0x8,0xb,0x5,0x6,0xf,0x0,0x3,0x4,0x7,0x2,0xc,0x1,0xa,0xe,0x9,  
        0xa,0x6,0x9,0x0,0xc,0xb,0x7,0xd,0xf,0x1,0x3,0xe,0x5,0x2,0x8,0x4,  
        0x3,0xf,0x0,0x6,0xa,0x1,0xd,0x8,0x9,0x4,0x5,0xb,0xc,0x7,0x2,0xe,  
        ],  
        [  
        0x2,0xc,0x4,0x1,0x7,0xa,0xb,0x6,0x8,0x5,0x3,0xf,0xd,0x0,0xe,0x9,  
        0xe,0xb,0x2,0xc,0x4,0x7,0xd,0x1,0x5,0x0,0xf,0xa,0x3,0x9,0x8,0x6,  
        0x4,0x2,0x1,0xb,0xa,0xd,0x7,0x8,0xf,0x9,0xc,0x5,0x6,0x3,0x0,0xe,  
        0xb,0x8,0xc,0x7,0x1,0xe,0x2,0xd,0x6,0xf,0x0,0x9,0xa,0x4,0x5,0x3,  
        ],  
        [  
        0xc,0x1,0xa,0xf,0x9,0x2,0x6,0x8,0x0,0xd,0x3,0x4,0xe,0x7,0x5,0xb,  
        0xa,0xf,0x4,0x2,0x7,0xc,0x9,0x5,0x6,0x1,0xd,0xe,0x0,0xb,0x3,0x8,  
        0x9,0xe,0xf,0x5,0x2,0x8,0xc,0x3,0x7,0x0,0x4,0xa,0x1,0xd,0xb,0x6,  
        0x4,0x3,0x2,0xc,0x9,0x5,0xf,0xa,0xb,0xe,0x1,0x7,0x6,0x0,0x8,0xd,  
        ],  
        [  
        0x4,0xb,0x2,0xe,0xf,0x0,0x8,0xd,0x3,0xc,0x9,0x7,0x5,0xa,0x6,0x1,  
        0xd,0x0,0xb,0x7,0x4,0x9,0x1,0xa,0xe,0x3,0x5,0xc,0x2,0xf,0x8,0x6,  
        0x1,0x4,0xb,0xd,0xc,0x3,0x7,0xe,0xa,0xf,0x6,0x8,0x0,0x5,0x9,0x2,  
        0x6,0xb,0xd,0x8,0x1,0x4,0xa,0x7,0x9,0x5,0x0,0xf,0xe,0x2,0x3,0xc,  
        ],  
        [  
        0xd,0x2,0x8,0x4,0x6,0xf,0xb,0x1,0xa,0x9,0x3,0xe,0x5,0x0,0xc,0x7,  
        0x1,0xf,0xd,0x8,0xa,0x3,0x7,0x4,0xc,0x5,0x6,0xb,0x0,0xe,0x9,0x2,  
        0x7,0xb,0x4,0x1,0x9,0xc,0xe,0x2,0x0,0x6,0xa,0xd,0xf,0x3,0x5,0x8,  
        0x2,0x1,0xe,0x7,0x4,0xa,0x8,0xd,0xf,0xc,0x9,0x0,0x3,0x5,0x6,0xb,  
        ],  
    ]  
    __k1 = [  
        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,  
    ]  
    __k2 = [  
        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,  
    ]  
    __k0 = [  
        1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,  
    ]  
    __hex_bin = {  
        '0':'0000','1':'0001','2':'0010','3':'0011',  
        '4':'0100','5':'0101','6':'0110','7':'0111',  
        '8':'1000','9':'1001','a':'1010','b':'1011',  
        'c':'1100','d':'1101','e':'1110','f':'1111',  
        ' ':'0000'  
    }  
  
    __re = lambda t, s: ''.join(s[i-1] for i in t)  
  
    __IP = partial(__re, __ip)  
    __IP1 = partial(__re, __ip1)  
    __E = partial(__re, __e)  
    __P = partial(__re, __p)  
    __K1 = partial(__re, __k1)  
    __K2 = partial(__re, __k2)  
  
    __B = partial( lambda hex_bin, s: ''.join(hex_bin[w]  for w in ''.join('%2x' % ord(w) for w in s)), __hex_bin)  
   
    __DB = partial( lambda s: ''.join(chr(int(s[i:i+8], 2)) for i in range(0, len(s), 8)))  
    
    __S = partial( lambda hex_bin, __s, s: ''.join(hex_bin['%x' % __s[i][int(s[i*6]+s[i*6+5], 2)*16 + int(s[i*6+1:i*6+5], 2)]] for i in range(8)),__hex_bin, __s)  
   
    __F = partial( lambda s, k: ''.join('0' if s[i]==k[i] else '1' for i in range(len(s))))  
    
    __K0 = partial( lambda k0, K2, k: map(K2,(k[k0[i]:28]+k[0:k0[i]] + k[k0[i]+28:56]+k[28:k0[i]+28] for i in range(16))),__k0, __K2)  
    
    __K = partial( lambda K1, K0, k: K0(K1(k)),__K1, __K0)  
  
    def __init__(self):  
        pass  
  
    def input_key(self, key, base=10):  
        if base == 2:  
            pass  
        elif base == 16:  
            key = ''.join(self.__class__.__hex_bin[w] for w in key)  
        else:  
            key = self.__class__.__B(key)  
        self.__k = self.__class__.__K(key)  
  
    def __code(self, s, k):  
        s = self.__IP(s)  
        l, r = s[0:32], s[32:64]  
        for i in range(16):  
            r_t = r  
            r = self.__E(r)  
            r = self.__F(r, k[i])  
            r = self.__S(r)  
            r = self.__P(r)  
            r = self.__F(r, l)  
            l = r_t  
        return self.__class__.__IP1(r+l)  
  
    def encode(self, s):  
        a = ''  
        s += ' ' * ((8-len(s)%8)%8)  
        for i in range(0, len(s), 8):  
            before = self.__class__.__B(s[i:i+8])  
            after = self.__code(before, self.__k)  
            a += '%16x' % int(after, 2)  
        return ''.join(w if w!=' ' else '0' for w in a)  
  
    def decode(self, s):  
        a = ''  
        s.lower()  
        for i in range(0, len(s), 16):  
            before = ''.join(self.__class__.__hex_bin[s[j]] for j in range(i, i+16))  
            after = self.__code(before, self.__k[::-1])  
            a += self.__class__.__DB(after)  
        return a.rstrip()  
  
  
if __name__ == '__main__':  
    d = DES()
    key="this is a key"
    d.input_key(key)  
    s = 'this is a text' 
    print "m=",s
    print "key=",key
    print "Encrypt:",
    a = d.encode(s)  
    print a
    print "Decrypt:",
    b = d.decode(a)  
    print b  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章