Python AES256加密


2021-03-26 修改:
本次修改盡量和其他語言中使用的關鍵保持一致,目前只做了PKCS7PADDING的填充方案和BASE64的輸出格式

基礎知識
# 在Linux操作系統下,Python3的默認環境編碼變為了utf-8編碼,所以在編寫代碼的時候,字符串大部分都是以utf-8處理
UTF-8:
1byte = 8bit
1個英文字符 = 1byte
1個中文字符 = 3byte

128bit = 16byte = 16個英文字符
192bit = 24byte = 24個英文字符
256bit = 32byte = 32個英文字符
AES256概念

AES是一種對稱加密算法,對稱指加密和解密使用同一個密鑰; 256指密鑰的長度是256bit,即32個英文字符的長度;密鑰的長度決定了AES加密的輪數

AES256加密參數
  • 密鑰: 一個32byte的字符串, 常被叫為key
  • 明文: 待加密的字符串;字節長度(按byte計算)必須是16的整數倍,因此,明文加密之前需要被填充
  • 模式: 加密模式,常用的有ECB、CBC;具體含義見參考鏈接
  • iv 偏移量: CBC模式下需要是16byte字符串; ECB下不需要
參考代碼
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""
pip install pycryptodome
ord(): 返回對應字符的ascii碼
chr(): 返回ascii碼對應的字符, ascii碼可以用十進制,也可以用十六進制
"""


import base64
from Crypto.Cipher import AES
from Crypto.Cipher.AES import MODE_CBC, MODE_ECB


PKCS7PADDING = 0
PKCS5PADDING = 1

BASE64 = 0
HEX = 1


class AesCrypto:
    def __init__(self, key, mode=MODE_ECB, padding=PKCS7PADDING, iv=None, encode_type=BASE64):
        """
        :param key: 密鑰, 32byte=>256, 16byte=>128, 24byte=>192
        :param mode: 加密模式
        :param iv: 16byte 長度字符串
        :param padding: 填充方式
        :param encode_type: 輸出格式
        """

        self.key = key.encode()
        self.mode = mode
        self.encode_type = encode_type
        self.iv = iv
        if self.iv:
            self.iv = self.iv.encode()

        if padding == PKCS7PADDING:
            self.padding_func = self.pkcs7padding
            self.unpadding_func = self.unpadding
        else:
            raise Exception('padding is invalid')

    def pkcs7padding(self, text:str, bs=16):
        """明文使用PKCS7填充 """
        remainder = bs - len(text.encode()) % bs
        padding_text = chr(remainder) * remainder
        return text + padding_text

    def unpadding(self, text):
        """ 去掉填充字符 """
        remainder = text[-1]
        padding_text = ord(remainder) * remainder
        return text.rstrip(padding_text)

    def encrypt(self, text):
        """ 加密 """
        text = self.padding_func(text)
        # 注意:加密中的和解密中的AES.new()不能使用同一個對象,所以在兩處都使用了AES.new()
        kwargs = {
            'key': self.key,
            'mode': self.mode
        }
        if self.mode == MODE_CBC:
            kwargs['iv'] = self.iv
        text = AES.new(**kwargs).encrypt(text.encode())
        if self.encode_type == BASE64:
            return base64.b64encode(text).decode()

    def decrypt(self, text):
        """ 解密 """
        if self.encode_type == BASE64:
            text = base64.b64decode(text.encode())
        kwargs = {
            'key': self.key,
            'mode': self.mode
        }
        if self.mode == MODE_CBC:
            kwargs['iv'] = self.iv
        text = AES.new(**kwargs).decrypt(text)
        text = self.unpadding_func(text.decode())
        return text

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM