前言
密碼學作業之DES
簡介
DES全稱爲Data Encryption Standard,即數據加密標準,是一種使用密鑰加密的塊算法,1977年被美國聯邦政府的國家標準局確定爲聯邦資料處理標準(FIPS),並授權在非密級政府通信中使用,隨後該算法在國際上廣泛流傳開來。需要注意的是,在某些文獻中,作爲算法的DES稱爲數據加密算法(Data Encryption Algorithm,DEA),已與作爲標準的DES區分開來。
原理及步驟
初始置換
DES算法使用64位的密鑰key將64位的明文輸入塊變爲64位的密文輸出塊,並把輸出塊分爲L0、R0兩部分,每部分均爲32位。
加密處理–迭代過程
經過初始置換後,進行16輪完全相同的運算,在運算過程中數據與祕鑰結合。
函數f的輸出經過一個異或運算,和左半部分結合形成新的右半部分,原來的右半部分成爲新的左半部分
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