天天看點

python AES_CBC_128 PKCS7Padding

from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import algorithms
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import json
import base64

'''
AES/CBC/PKCS7Padding 加密解密
環境需求:
pip3 install pycryptodome
'''

class PrpCrypt(object):

    def __init__(self, key='0000000000000000'):
        self.key = '1111111111111111'.encode('utf-8')
        self.mode = AES.MODE_CBC
        self.iv = b'2222222222222222'
        # block_size 128位

    # 加密函數,如果text不足16位就用空格補足為16位,
    # 如果大于16但是不是16的倍數,那就補足為16的倍數。
    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        text = text.encode('utf-8')

        # 這裡密鑰key 長度必須為16(AES-128),24(AES-192),或者32 (AES-256)Bytes 長度
        # 目前AES-128 足夠目前使用

        text=self.pkcs7_padding(text)

        self.ciphertext = cryptor.encrypt(text)

        # 因為AES加密時候得到的字元串不一定是ascii字元集的,輸出到終端或者儲存時候可能存在問題
        # 是以這裡統一把加密後的字元串轉化為16進制字元串
        # return b2a_hex(self.ciphertext).decode().upper()
        return(base64.b64encode(self.ciphertext))

    @staticmethod
    def pkcs7_padding(data):
        if not isinstance(data, bytes):
            data = data.encode()

        padder = padding.PKCS7(algorithms.AES.block_size).padder()

        padded_data = padder.update(data) + padder.finalize()

        return padded_data

    @staticmethod
    def pkcs7_unpadding(padded_data):
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
        data = unpadder.update(padded_data)

        try:
            uppadded_data = data + unpadder.finalize()
        except ValueError:
            raise Exception('無效的加密資訊!')
        else:
            return uppadded_data

    # 解密後,去掉補足的空格用strip() 去掉
    def decrypt(self, text):
        #  偏移量'iv'
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt(base64.b64decode(text))
        # plain_text = cryptor.decrypt(a2b_hex(text))
        # return plain_text.rstrip('\0')
        return bytes.decode(plain_text).rstrip("\x01").\
            rstrip("\x02").rstrip("\x03").rstrip("\x04").rstrip("\x05").\
            rstrip("\x06").rstrip("\x07").rstrip("\x08").rstrip("\x09").\
            rstrip("\x0a").rstrip("\x0b").rstrip("\x0c").rstrip("\x0d").\
            rstrip("\x0e").rstrip("\x0f").rstrip("\x10")

    def dict_json(self, d):
        '''python字典轉json字元串, 去掉一些空格'''
        j = json.dumps(d).replace('": ', '":').replace(', "', ',"').replace(", {", ",{")
        return j

# 加解密
if __name__ == '__main__':
    import json
    pc = PrpCrypt()  # 初始化密鑰
    a = "18511337566"
    print("加密前:%s" % a)
    b = pc.encrypt(a)
    print("解密後:%s" % b)
    c= pc.decrypt(d)
    print(c)