1. 程式人生 > >Python AES加密

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()