Python AES加密
AES:Advanced Encryption Standard,高階加密標準,是最常的對稱加密演算法。(加密和解密用相同的金鑰)
簡單記憶:C = E(K,P):明文P,金鑰K,AES加密函式組成E,密文C。
AES是分組密碼,即將明文分成一組一組的,每組長度相等,每次加密一組資料,直到整個加密完成。
AES分組的長度只能是128位,即分組為16個位元組(每個位元組8位),簡單的說:明文P必須是長度為16的整數倍,字串或數字。
金鑰的長度可以使用128位、192位或256位,簡單的說:金鑰K可以是長度為16,24,32的字串或數字。分別對應的加密輪數為10,12,14。
至於為什麼會是這樣呢?AES規範是這麼寫的。詳細的解釋見如下連結:
https://blog.csdn.net/qq_28205153/article/details/55798628,有圖,有原理解析,這裡就不囉嗦了。
AES只是基本演算法,實現AES有幾個模式:ECB、CBC、CFB、OFB,詳細說明見如下連結:
https://blog.csdn.net/aaaaatiger/article/details/2525561
測試環境:win10 + Python3.5 + PyCrypto
推薦安裝:pip install pycryptodome
PyCrypto支援DES、AES加密以及MD5、SHA各種HASH運算。這裡使用CBC模式,即AES.new(key, AES.MODE_CBC,iv)函式,預設iv是16個0(這個稱為初始化向量),由於是分組加密,所以下一組的iv,就用前一組的加密的密文來充當,指定IV來進行加解密,可以增加破解難度。(其他模式,例如:AES.new(key)、AES.new(key, AES.MODE_ECB))
注:記得將key,iv轉換成:b"23143214",python3.x裡預設的str是(py2.x裡的)unicode,所以需要encode一下
# coding=utf-8 from Crypto.Cipher import AES import json import base64 import requests import unittest ''' AES加密介面測試 ''' class AESInterfaceTest(unittest.TestCase): def setUp(self): # 設定block_size的大小為16 self.bs = AES.block_size # 對傳入self.pad的內容自動補全16位,填充內容是“16-len(s)”對應的ascii字元 self.pad = lambda s: s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) self.unpad = lambda s: s[0:-ord(s[-1])] # 待測介面地址 self.interface_url = "http://127.0.0.1:8000/api/user_list/" # 金鑰key需要與開發協商提供,或在介面文件中定義 key = 'DLsi60ewaW32ojd1' self.key = key.encode('utf-8') # b"****" self.iv = b"7683425105789011" # 可以自定義,也可以是隨機值 self.mode = AES.MODE_CBC def encrypt_base64(self, src): ''' 對金鑰key進行加密,生成base64字串 ''' return base64.urlsafe_b64decode(src) def encrypt_aes(self, src, key, iv): ''' 生成AES密文 :param src: 明文P :param key: 金鑰K :return:密文C ''' cryptor = AES.new(key, self.mode, iv) src_str = self.pad(src) src_byte = src_str.encode('utf-8') ciphertext = cryptor.encrypt(src_byte) # AES加密 aes_base64 = self.encrypt_base64(ciphertext) # 生成base64 print(aes_base64) return aes_base64 def test_aes_interface(self): '''測試加密介面''' playload = {'user':'xxx', 'phone':''} data = json.dumps(playload) # 加密 encode_data = self.encrypt_aes(data, self.key, self.iv) r = requests.post(self.interface_url, data={"data": encode_data}) result = r.text print(result) if __name__ == '__main__': unittest.main()