簡介
對稱加密(也叫私鑰加密, 單密鑰加密)指加密和解密使用相同密鑰的加密算法,加密密鑰和解密密鑰是相同的,對稱算法的安全性依賴於密鑰,泄漏密鑰就意味着任何人都可以對他們發送或接收的消息解密,所以密鑰的保密性對通信的安全性至關重要。
常見的對稱加密算法
1, DES: 已破解,不再安全,是對稱加密算法的基石,具有學習價值, 有時間可以研究
2, DESede: 三重DES, 早於AES出現來替代DES ,計算密鑰時間太長、加密效率不高,所以也基本上不用
3, AES: 最常用的對稱加密算法, 密鑰建立時間短、靈敏性好、內存需求低
4, IDEA: 常用於電子郵件加密
AES詳解:
使用最常用的對稱加密算法AES(分爲 ECB CBC CFB等模式)
ECB(電子密碼本模式) :是最簡單的加密模式, 加密前使用根據加密塊的大小,將其分爲若干塊, 然後將每一塊都單獨加密, 解密也是一樣
CBC(密碼分組鏈接模式): 同樣先將加密塊分成若干塊, 每一塊加密之前會與前一塊的密文進行一次異或運算, 之後再用加密器進行加密, 但由於第一塊密文沒有上一塊, 所以引入了 一個 初始化向量(IV)的比特序列來代替, 這樣加密的好處, 即便上一塊分組與下一塊分組的內容相同, 但在加密後,它們不一定會相同, 所以這種模式會比 ECB 模式更加安全。 正是因爲這種鏈式加密的方式,每個分組的加密都依賴上一個分組, 應該是不能像ECB那樣實現並行加密, 速度會受到一定影響
關於 初始化向量(IV)的一點擴展, SSL/TLS協議使用的就是cbc模式進行數據加密, 在1.0 和 1.1 版本他們的cbc加密模式有一定的不同, 1.0版本的IV不是隨機生成的, 而是通過上一次加密模式的最後一個分組, 使得 攻擊者 可以輕鬆拿到IV, 算是一個比較大的漏洞, 還有一些基於cbc模式的TLS攻擊實施, 之後再詳細瞭解。。。, 這些攻擊實施大部分依賴於服務器的響應, 如果單純對字符數據進行加密,用於儲存, IV也可以不用隨機生成
特點
1,對稱加密算法(對於常用的算法)最明顯的特點是 效率高, 速度快, 計算量小, 和使用長密鑰時的難破解性
2,安全性來說 , 主要取決於 密鑰的保存, 如果多方通信,每一方都需要保留一份密鑰, 導致泄漏的機率增加
3, 對於一個組織(公司)的用戶來說 , 如果 使用對稱加密交換數據 , 若每兩個人之間使用對稱加密來交換數據,那麼就會增加一個密鑰, 如果用戶有n個, 則需要 n ×(n - 1)個密鑰, 可見相當複雜, 不利於管理, 但如果都使用 同一個 或幾個 密鑰, 泄漏後導致的風險問題同樣很令人頭疼
使用python實踐
利用python完成AES的加解密
class AesCrypt():
def __init__(self, model):
self.encode_ = 'utf-8'
self.model = model
self.key = self.add_16('123456') # 加密的密鑰
self.iv = bytes('xxxxxxxxxxxxxxxx', encoding='utf-8')
def add_16(self,par):
"""用於補全位數 16的倍數"""
par = par.encode(self.encode_)
text_length = len(par)
# 計算需要填充的位數
amount_to_pad = 16 - (text_length % 16)
if amount_to_pad == 0:
amount_to_pad = 16
# 獲得補位所用的字符
pad = bytearray([amount_to_pad])
return par + pad * amount_to_pad
def _get_aes(self):
"""ECB, CBC 模式"""
if self.model == 'ECB':
return AES.new(self.key,AES.MODE_ECB)
elif self.model == 'CBC':
return AES.new(self.key,AES.MODE_CBC,self.iv)
def aesencrypt(self,text):
"""加密"""
text = self.add_16(text)
self.encrypt_text = self._get_aes().encrypt(text)
return base64.encodebytes(self.encrypt_text).decode().strip()
def aesdecrypt(self,text):
"""解密"""
text = base64.decodebytes(text.encode(self.encode_))
self.decrypt_text = self._get_aes().decrypt(text)
return self.decrypt_text.decode(self.encode_).strip('\0')