一、前言
AES,高級加密標準(Advanced Encryption Standard)。是用來替代 DES,目前比較流行的對稱加密算法。與上一篇博文提到過的 RSA 非對稱算法不同,對稱加密算法也就是加密和解密用相同的密鑰,具體的加密流程如下圖:
明文 P:
等待加密的數據。
密鑰 K:
用來加密明文的密碼,在對稱加密算法中,加密與解密的密鑰是相同的。密鑰為接收方與發送方協商產生,但不可以直接在網絡上傳輸,否則會導致密鑰泄漏,通常是通過非對稱加密算法加密密鑰,然后再通過網絡傳輸給對方,或者直接面對面商量密鑰。密鑰是絕對不可以泄漏的,否則會被攻擊者還原密文,竊取機密數據。
AES 加密函數:
設 AES 加密函數為 E,則 C = E(K, P),其中 P 為明文,K 為密鑰,C 為密文。也就是說,把明文 P 和密鑰 K 作為加密函數的參數輸入,則加密函數 E 會輸出密文 C。
密文 C:
經過 AES 加密后的數據。
AES 解密函數:
設 AES 解密函數為 D,則 P = D(K, C),其中 C 為密文,K 為密鑰,P 為明文。也就是說,把密文 C 和密鑰 K 作為解密函數的參數輸入,則解密函數會輸出明文 P。
AES 只是個基本算法,實現 AES 有幾種模式,主要有 ECB、CBC、CFB 和 OFB 這幾種(其實還有個 CTR)。本章主要介紹最常用的 ECB 和 CBC 模式。
二、代碼實現與解析
1.ECB 模式
from Crypto.Cipher import AES
import base64
BLOCK_SIZE = 16 # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
def aesEncrypt(key, data):
'''
AES的ECB模式加密方法
:param key: 密鑰
:param data:被加密字符串(明文)
:return:密文
'''
key = key.encode('utf8')
# 字符串補位
data = pad(data)
cipher = AES.new(key, AES.MODE_ECB)
# 加密后得到的是bytes類型的數據,使用Base64進行編碼,返回byte字符串
result = cipher.encrypt(data.encode())
encodestrs = base64.b64encode(result)
enctext = encodestrs.decode('utf8')
print(enctext)
return enctext
def aesDecrypt(key, data):
'''
:param key: 密鑰
:param data: 加密后的數據(密文)
:return:明文
'''
key = key.encode('utf8')
data = base64.b64decode(data)
cipher = AES.new(key, AES.MODE_ECB)
# 去補位
text_decrypted = unpad(cipher.decrypt(data))
text_decrypted = text_decrypted.decode('utf8')
print(text_decrypted)
return text_decrypted
if __name__ == '__main__':
key = '5c44c819appsapi0'
data = 'herish acorn'
ecdata = aesEncrypt(key, data)
aesDecrypt(key, ecdata)
結果如下:
0FyQSXu3Q9Q13JGf4F74jA==
herish acorn
檢測結果可以前往在線 AES 加密解密進行驗證。
ECB 是最簡單的塊密碼加密模式,加密前根據加密塊大小(如 AES 為128位)分成若干塊,之后將每塊使用相同的密鑰單獨加密,解密同理。相對其他模式沒有偏移量的設置,簡單點,安全性差點。
AES 加密有 AES-128、AES-192、AES-256 三種,分別對應三種密鑰長度 128bits(16字節)、192bits(24字節)、256bits(32字節)。當然,密鑰越長,安全性越高,加解密花費時間也越長。默認的是AES-128,其安全性完全夠用。
pad 和 unpad 分別是填充函數和逆填充函數。因為 AES 加密對加密文本有長度要求,必須是密鑰字節數的倍數。這里的 key 的長度是 16 個字節。
關于填充算法,簡單解釋就是缺幾位就補幾:填充字符串由一個字節序列組成,每個字節填充該填充字節序列的長度。Python 代碼中 ECB 模式進行 AES 加密默認就是 pkcs7padding 填充。
2.CBC 模式
CBC 模式對于每個待加密的密碼塊在加密前會先與前一個密碼塊的密文異或然后再用加密器加密。第一個明文塊與一個叫初始化向量的數據塊異或。
from Crypto.Cipher import AES
import base64
# 密鑰(key), 密斯偏移量(iv) CBC模式加密
BLOCK_SIZE = 16 # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
vi = '0102030405060708'
def AES_Encrypt(key, data):
data = pad(data)
# 字符串補位
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
encryptedbytes = cipher.encrypt(data.encode('utf8'))
# 加密后得到的是bytes類型的數據,使用Base64進行編碼,返回byte字符串
encodestrs = base64.b64encode(encryptedbytes)
# 對byte字符串按utf-8進行解碼
enctext = encodestrs.decode('utf8')
return enctext
def AES_Decrypt(key, data):
data = data.encode('utf8')
encodebytes = base64.decodebytes(data)
# 將加密數據轉換位bytes類型數據
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
text_decrypted = cipher.decrypt(encodebytes)
# 去補位
text_decrypted = unpad(text_decrypted)
text_decrypted = text_decrypted.decode('utf8')
print(text_decrypted)
return text_decrypted
if __name__ == '__main__':
key = '5c44c819appsapi0'
data = 'herish acorn'
enctext = AES_Encrypt(key, data)
print(enctext)
AES_Decrypt(key, enctext)
結果如下:
svAg4qrFNphvwS47DLSb2A==
herish acorn
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
