1、對稱加密 (Symmetric Key Encryption) python
對稱加密是最快速、最簡單的一種加密方式,加密(encryption)與解密(decryption)用的是一樣的密鑰(secret key)。對稱加密有不少種算法,因爲它效率很高,因此被普遍使用在不少加密協議的核心當中。自1977年美國頒佈DES(Data Encryption Standard)密碼算法做爲美國數據加密標準以來,對稱密碼體制迅速發展,獲得了世界各國的關注和廣泛應用。對稱密碼體制從工做方式上能夠分爲分組加密和序列密碼兩大類。git
對稱加密算法的優勢:算法公開、計算量小、加密速度快、加密效率高。github
對稱加密算法的缺點:交易雙方都使用一樣鑰匙,安全性得不到保證。此外,每對用戶每次使用對稱加密算法時,都須要使用其餘人不知道的唯一鑰匙,這會使得發收信雙方所擁有的鑰匙數量呈幾何級數增加,密鑰管理成爲用戶的負擔。對稱加密算法在分佈式網絡系統上使用較爲困難,主要是由於密鑰管理困難,使用成本較高。而與公開密鑰加密算法比起來,對稱加密算法可以提供加密和認證卻缺少了簽名功能,使得使用範圍有所縮小。算法
對稱加密一般使用的是相對較小的密鑰,通常小於256 bit。由於密鑰越大,加密越強,但加密與解密的過程越慢。數組
分組密碼:也叫塊加密(block cyphers),一次加密明文中的一個塊。是將明文按必定的位長分組,明文組通過加密運算獲得密文組,密文組通過解密運算(加密運算的逆運算),還原成明文組,有 ECB、CBC、CFB、OFB 四種工做模式。安全
序列密碼:也叫流加密(stream cyphers),一次加密明文中的一個位。是指利用少許的密鑰(制亂元素)經過某種複雜的運算(密碼算法)產生大量的僞隨機位流,用於對明文位流的加密。解密是指用一樣的密鑰和密碼算法及與加密相同的僞隨機位流,用以還原明文位流。網絡
經常使用對稱加密算法包括 DES、3DES、AESapp
1. DES(Data Encryption Standard):數據加密標準,速度較快,適用於加密大量數據的場合。
2. 3DES(Triple DES):是基於DES,對一塊數據用三個不一樣的密鑰進行三次加密,強度更高。
3. AES(Advanced Encryption Standard):高級加密標準,是下一代的加密算法標準,速度快,安全級別高,支持12八、19二、25六、512位密鑰的加密。dom
算法特徵
1. 加密方和解密方使用同一個密鑰。
2. 加密解密的速度比較快,適合數據比較長時的使用。
3. 密鑰傳輸的過程不安全,且容易被破解,密鑰管理也比較麻煩。分佈式
2、簡介對稱加密算法 Des
一、數據加密標準 Des
(1)Des 設計理念
Des 設計中使用了分組密碼設計的兩個原則:混淆(confusion)和擴散(diffusion),其目的是抗擊敵手對密碼系統的統計分析。混淆是使密文的統計特性與密鑰的取值之間的關係 儘量複雜化,以使密鑰和明文以及密文之間的依賴性對密碼分析者來講是沒法利用的。擴散的做用就是將每一位明文的影響儘量迅速地做用到較多的輸出密文位中,以便在大量的 密文中消除明文的統計結構,而且使每一位密鑰的影響儘量迅速地擴展到較多的密文位中,以防對密鑰進行逐段破譯。
二、Des 加密算法結構流程
三、Des 加密算法電子編碼本 ECB (Electronic Code Book,電子編碼本) 模式流程
(1)ECB 模式 & 性能
ECB 模式是最簡單的加密模式,明文消息被分紅固定大小的塊(分組),而且每一個塊被單獨加密。每一個塊的加密和解密都是獨立的,且使用相同的方法進行加密,因此能夠進行並行計算,可是這種方法一旦有一個塊被破解,使用相同的方法能夠解密全部的明文數據,安全性比較差。適用於數據較少的情形,加密前須要把明文數據填充到塊大小的整倍數。
ECB算法優勢:
簡單、孤立,每一個塊單獨運算。適合並行運算。傳輸錯誤通常隻影響當前塊。
ECB算法缺點:
同明文輸出同密文,可能致使明文攻擊。
(2)ECB 加密 & 解密流程
Encryption:
Decryption:
四、Des 分組加密所需參數
(1)Key:64位主密鑰
(2)明文:64位的倍數
(3)密文:64位的倍數
(4)分組模式填充方式:PKCS5
(5)分組密碼工做模式:EBC模式
五、Des 加密過程
(1)初始置換(IP)
根據初始置換表,對相應明文位置上的二進制進行置換操做,即把64 位的數據塊的原第 58 位換到第一位,原第 50 位換到第二位.依此類推。目的在於打亂明文中各位的次序。
(2)子密鑰生成
從用戶處取得一個 64 位長的密鑰key ,去除 64 位密鑰中做爲奇偶校驗位的第 八、1六、2四、3二、40、4八、5六、64 位,剩下的 56 位做爲有效輸入密鑰。把生成的 56 位輸入密鑰分紅均等的 A,B 兩部分,每部分爲 28 位,使用置換選擇 1 對剩下的 58 位打亂,輸出左 28 位 C 和右 28 位 D。兩個部分都進行向左移位,移位後的兩部分數據有兩個做用。第一輸出子密鑰,每 i 輪兩部分合在一塊兒進行進行置換選擇 2 獲得迭代運算的第 i 個子密鑰,第二做爲下一輪子密鑰運算。總共 16 輪運算(i=1,2,9,6 左移 1 位,其他 2 位)。
(3)16 輪迭代運算 (Des 核心)
首先將二進制分爲兩個 32 位的部分:left 和 right。保持 left 不變,根據擴展置換表把 right 由 32 位擴展成 48 位。把擴展後的 48 位 right 與第 i 次迭代生成的 48 位子密鑰按位異或運算,造成一個新的 48 位的 right。而後與主密鑰生成的 48 位子密鑰異或操做,而後進行 S 盒代換,獲得一個 32 位的二進制數據,將數據進行 P 盒置換後,與 left 進行異或操做,結果做爲下一輪迭代運算的 right 部分。上一輪 right 部分做爲下一輪運算的 left 部分。第 16 次迭代不交換二者的數值。
(4)初始逆置換
16輪迭代運算後,依據初始逆置換表,對相應位置的二進制數進行置換操做。最後獲得密文。
六、Des 解密過程
Des 算法是對稱的,既可用加密又可用於解密,只不過在16次迭代中使用的密鑰次序正好相反。解密時,第一次迭代使用子密鑰K16,依次類推。
七、分組密碼工做方式
ECB,將明文消息分紅 n 個 m bit 組(m 一般爲 64),若是長度不是 m 整數倍,則在明文末尾進行填充 (本次實驗採用PKCS5)
3、實現對稱加密算法 Des
一、語言 & 環境
(1)語言
Python
(2)環境
Python版本:python 3.7
Python工具:PyCharm Professional
二、操做流程
(1)在 < text.txt > 文件中讀取須要加密的文本
(2)在 < key.txt > 文件中寫入隨機產生固定長度的Key
(3)在 < ciphertext.txt > 文件中寫入DES加密、Base64編碼後的數據
(4)在 < plaintext.txt > 文件中寫入Base64解碼、DES解密後的數據
三、主要代碼
(1)Main 函數
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 if __name__ == '__main__': 2 key = getRandomString() 3 with open('text.txt', 'r+') as fr: 4 text = (fr.read()) # 從 'text.txt' 文件中讀取加密文本 5 D = Des() 6 C = (base64.b64encode((D.encrypt(key, text, True)).encode("utf8"))).decode() # 加密 7 C1 = (base64.b64decode(C)).decode() 8 P = D.decrypt(key, C1, True) # 解密 9 with open('key.txt', 'w+') as fwk: # 存儲密鑰 10 fwk.write(key) 11 with open('ciphertext.txt', 'w+') as fwc: # 存儲密文 12 fwc.write(C) 13 with open('plaintext.txt', 'w+') as fwp: # 存儲明文 14 fwp.writelines(P) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(2)Encryption
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def encrypt(self, key, text, padding): # DES 加密函數 2 return self.run(key, text, ENCRYPT, padding) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(3)Decryption
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def decrypt(self, key, text, padding): # DES 解密函數 2 return self.run(key, text, DECRYPT, padding) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(4)字符串和比特數組之間相互轉換
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def string_to_bit_array(text): # 字符串-->bit數組 2 array = list() 3 for char in text: 4 binval = binvalue(char, 8) # 得到每一個字符的二進制 5 array.extend([int(x) for x in list(binval)]) 6 return array 7 8 def bit_array_to_string(array): # bit數組-->字符串 9 res = ''.join([chr(int(y, 2)) for y in [''.join([str(x) for x in bytes]) for bytes in nsplit(array, 8)]]) 10 return res < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(5)二進制處理
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def binvalue(val, bitsize): # 以給定大小的字符返回二進制值 2 binval = bin(val)[2:] if isinstance(val, int) else bin(ord(val))[2:] 3 if len(binval) > bitsize: 4 raise Exception("binary value larger than the expected size") 5 while len(binval) < bitsize: 6 binval = "0" + binval 7 return binval < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(6)列表劃分
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def nsplit(s, n): # 將列表拆分爲大小爲'n'的子列表 2 return [s[k:k + n] for k in range(0, len(s), n)] < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(7)獲取隨機固定長度序列 Key
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def getRandomString(slen=8): # 得到key的隨機序列 2 return ''.join(random.sample(string.ascii_letters + string.digits, slen)) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(8)初始化 Des 類
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def __init__(self): 2 self.password = None # 存放初始key 3 self.text = None # 存放明文 4 self.keys = list() # 存放key值列表集合 < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(9)PKCS5 模式 數據填充
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def addPadding(self): # PKCS5 進行數據填充,不論是否是BlockSize的整數倍都須要進行填充 2 pad_len = 8 - (len(self.text) % 8) 3 self.text += pad_len * chr(pad_len) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(10)數據填充移除
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def removePadding(self, data): # 刪除純文本的填充 2 pad_len = ord(data[-1]) 3 return data[:-pad_len] < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(11)獲取 Key 值集合列表
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def generatekeys(self): # 統計計算全部key值的算法 2 self.keys = [] 3 key = string_to_bit_array(self.password) 4 key = self.permut(key, CP_1) # 置換選擇1 初始化key 64bit-->56bit 5 g, d = nsplit(key, 28) # 分片 (g->LEFT),(d->RIGHT) 6 for i in range(16): # 16輪循環 7 g, d = self.shift(g, d, SHIFT[i]) # (g->LEFT),(d->RIGHT)分別進行移位操做 8 tmp = g + d # 合併 28bit+28bit-->56bit 9 self.keys.append(self.permut(tmp, CP_2)) # 置換選擇2 56bit-->48bit < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(12)Key 值移位函數
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def shift(self, g, d, n): # 每輪key值產生所需的函數 2 return g[n:] + g[:n], d[n:] + d[:n] < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(13)基本置換 擴展置換 壓縮置換
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def permut(self, block, table): # 置換(本程序中充當基本置換、壓縮置換的角色) 2 return [block[x - 1] for x in table] 3 4 def expand(self, block, table): # 擴展置換 5 return [block[x - 1] for x in table] < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(14)自定義 XOR 函數
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def xor(self, t1, t2): # 應用xor並返回結果列表 2 return [x ^ y for x, y in zip(t1, t2)] < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(15)S 盒代換
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 def substitute(self, d_e): # S盒代換 2 subblocks = nsplit(d_e, 6) # 將位數組分割爲6位的子列表 3 result = list() 4 for i in range(len(subblocks)): # 遍歷子列表 5 block = subblocks[i] 6 row = int(str(block[0]) + str(block[5]), 2) # 獲得第一位和最後一個位表示的行 7 column = int(''.join([str(x) for x in block[1:][:-1]]), 2) #獲得第2、3、4、五位表示的列 8 val = S_BOX[i][row][column] # 取爲本輪分配的SBOX[i]中的值 9 bin = binvalue(val, 4) # 將值轉換爲二進制 10 result += [int(x) for x in bin] # 將二進制值添加到結果列表中 11 return result < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
(16)16輪運算核心
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 1 for block in text_blocks: # 遍歷全部數據塊 2 block = string_to_bit_array(block) 3 block = self.permut(block, IP) # 數據塊的初始置換 4 g, d = nsplit(block, 32) # 數據塊分片 g(LEFT), d(RIGHT) 5 tmp = None 6 for i in range(16): # 16輪循環 7 d_e = self.expand(d, E) # d(RIGHT)的擴展 32bit-->48bit 8 if action == ENCRYPT: 9 tmp = self.xor(self.keys[i], d_e) 10 else: 11 tmp = self.xor(self.keys[15 - i], d_e) # 若是是解密的話先使用最後的key 12 tmp = self.substitute(tmp) # S盒代換 48bit-->32bit 13 tmp = self.permut(tmp, P) # P盒置換 14 tmp = self.xor(g, tmp) 15 g = d 16 d = tmp 17 result += self.permut(d + g, IP_1) # 數據塊的初始逆置換 18 final_res = bit_array_to_string(result) < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <
四、數據測試
(1)測試結果
(2)在 < text.txt > 文件中讀取須要加密的文本
(3)在 < key.txt > 文件中寫入隨機產生固定長度的Key
(4)在 < ciphertext.txt > 文件中寫入DES加密、Base64編碼後的數據
(5)在 < plaintext.txt > 文件中寫入Base64解碼、DES解密後的數據
五、該項目全部代碼文件上傳至 Github
(1)GitHub 主頁
https://github.com/Qftm
(2)Des 項目地址
https://github.com/Qftm/My-Des