Python实现AES加解密以及发送加解密请求

AES加解密的类

python解释器用的是3.9,安装Crypto相关模块报错的解决方案:
https://stackoverflow.com/questions/19623267/importerror-no-module-named-crypto-cipher

import base64
from binascii import b2a_hex, a2b_hex
from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad


class AESUtil(object):
    # 使用ECB模式加密
    MODE = AES.MODE_ECB
    # 使用默认的pkcs7 padding
    PAD_STYLE = 'pkcs7'
    ENCODING = 'UTF-8'

    # key长度只能为16或24或32,分别对应AES-128、AES-192、AES-256
    @staticmethod
    def encrypt(plaintext: str, key: str) -> str:
        # 将密钥编码为UTF-8格式的bytes
        key_bytes = key.encode(AESUtil.ENCODING)
        # 创建AES对象
        cipher = AES.new(key_bytes, AESUtil.MODE)
        # 将明文编码为UTF-8格式的bytes
        plaintext_bytes = plaintext.encode(AESUtil.ENCODING)
        # 为编码后的明文添加padding
        plaintext_bytes_padded = pad(plaintext_bytes, AES.block_size, AESUtil.PAD_STYLE)
        # 执行加密
        ciphertext_bytes = cipher.encrypt(plaintext_bytes_padded)
        # 将加密后的bytes进行base64编码
        # 注意:不能用encodebytes!否则会每76个字符增加一个换行符,见:https://docs.python.org/zh-cn/3/library/base64.html
        ciphertext_base64_bytes = base64.b64encode(ciphertext_bytes)
        # 将base64编码过的bytes,解码为Python中使用的字符串类型(即unicode字符串)
        ciphertext = ciphertext_base64_bytes.decode(AESUtil.ENCODING)
        return ciphertext

    @staticmethod
    def decrypt(ciphertext: str, key: str) -> str:
        # 将密钥编码为UTF-8格式的bytes
        key_bytes = key.encode(AESUtil.ENCODING)
        # 创建AES对象
        decrypter = AES.new(key_bytes, AESUtil.MODE)
        # 将密文编码为UTF-8格式的(同时也是base64编码的)bytes
        ciphertext_base64_bytes = ciphertext.encode(AESUtil.ENCODING)
        # 将base64编码的bytes,解码为原始的密文bytes
        ciphertext_bytes = base64.b64decode(ciphertext_base64_bytes)
        # 解码为明文
        plaintext_bytes_padded = decrypter.decrypt(ciphertext_bytes)
        # 去掉Padding
        plaintext_bytes = unpad(plaintext_bytes_padded, AES.block_size, AESUtil.PAD_STYLE)
        # 将UTF-8格式编码的明文bytes,解码为Python中的字符串类型(即unicode字符串)
        plaintext = plaintext_bytes.decode(AESUtil.ENCODING)
        return plaintext

class PrpCrypt(object):

    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.mode = AES.MODE_CBC
        self.iv = Random.new().read(AES.block_size)

    # 加密函数,如果text不足16位就用空格补足为16位,
    # 如果大于16当时不是16的倍数,那就补足为16的倍数。
    def encrypt(self, text):
        text = text.encode('utf-8')
        cryptor = AES.new(self.key, self.mode, self.iv)
        # 这里密钥key 长度必须为16(AES-128),
        # 24(AES-192),或者32 (AES-256)Bytes 长度
        # 目前AES-128 足够目前使用
        length = 16
        count = len(text)
        if count < length:
            add = (length - count)
            # \0 backspace
            text = text + ('\0' * add).encode('utf-8')
        elif count > length:
            add = (length - (count % length))
            text = text + ('\0' * add).encode('utf-8')
        self.ciphertext = cryptor.encrypt(text)
        # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
        # 所以这里统一把加密后的字符串转化为16进制字符串
        return b2a_hex(self.ciphertext)

    # 解密后,去掉补足的空格用strip() 去掉
    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt(a2b_hex(text))
        return bytes.decode(plain_text).rstrip('\0')



if __name__ == '__main__':
    aes_key = 'sbsbsbsbsbsbsbsb'
    pc = PrpCrypt(aes_key)  # 初始化密钥
    data = "xxx123"
    print("原始data: ", data)
    print("--------------第1种方法符合服务端的AES对称加密算法: ")
    e1 = AESUtil.encrypt(data, aes_key)
    d1 = AESUtil.decrypt(e1, aes_key)
    print("加密:", e1)
    print("解密:", d1)

    print("--------------第2种方法不符合服务端的AES对称加密算法: ")
    e2 = pc.encrypt(data)  # 加密
    d2 = pc.decrypt(e2).encode()  # 解密
    print("加密:", e2)
    print("解密:", d2)

    """
        原始data:  xxx123
        --------------第1种方法符合服务端的AES对称加密算法: 
        加密: fRpmp7q6laM5A96Nr/ZyPA==
        解密: xxx123
        --------------第2种方法不符合服务端的AES对称加密算法: 
        加密: b'8efdb7c72cd323ee204e2f290e6becd5'
        解密: b'xxx123'
    """

发动加密的post请请求

import base64
from binascii import b2a_hex, a2b_hex
from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad


class AESUtil(object):
    # 使用ECB模式加密
    MODE = AES.MODE_ECB
    # 使用默认的pkcs7 padding
    PAD_STYLE = 'pkcs7'
    ENCODING = 'UTF-8'

    # key长度只能为16或24或32,分别对应AES-128、AES-192、AES-256
    @staticmethod
    def encrypt(plaintext: str, key: str) -> str:
        # 将密钥编码为UTF-8格式的bytes
        key_bytes = key.encode(AESUtil.ENCODING)
        # 创建AES对象
        cipher = AES.new(key_bytes, AESUtil.MODE)
        # 将明文编码为UTF-8格式的bytes
        plaintext_bytes = plaintext.encode(AESUtil.ENCODING)
        # 为编码后的明文添加padding
        plaintext_bytes_padded = pad(plaintext_bytes, AES.block_size, AESUtil.PAD_STYLE)
        # 执行加密
        ciphertext_bytes = cipher.encrypt(plaintext_bytes_padded)
        # 将加密后的bytes进行base64编码
        # 注意:不能用encodebytes!否则会每76个字符增加一个换行符,见:https://docs.python.org/zh-cn/3/library/base64.html
        ciphertext_base64_bytes = base64.b64encode(ciphertext_bytes)
        # 将base64编码过的bytes,解码为Python中使用的字符串类型(即unicode字符串)
        ciphertext = ciphertext_base64_bytes.decode(AESUtil.ENCODING)
        return ciphertext

    @staticmethod
    def decrypt(ciphertext: str, key: str) -> str:
        # 将密钥编码为UTF-8格式的bytes
        key_bytes = key.encode(AESUtil.ENCODING)
        # 创建AES对象
        decrypter = AES.new(key_bytes, AESUtil.MODE)
        # 将密文编码为UTF-8格式的(同时也是base64编码的)bytes
        ciphertext_base64_bytes = ciphertext.encode(AESUtil.ENCODING)
        # 将base64编码的bytes,解码为原始的密文bytes
        ciphertext_bytes = base64.b64decode(ciphertext_base64_bytes)
        # 解码为明文
        plaintext_bytes_padded = decrypter.decrypt(ciphertext_bytes)
        # 去掉Padding
        plaintext_bytes = unpad(plaintext_bytes_padded, AES.block_size, AESUtil.PAD_STYLE)
        # 将UTF-8格式编码的明文bytes,解码为Python中的字符串类型(即unicode字符串)
        plaintext = plaintext_bytes.decode(AESUtil.ENCODING)
        return plaintext

class PrpCrypt(object):

    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.mode = AES.MODE_CBC
        self.iv = Random.new().read(AES.block_size)

    # 加密函数,如果text不足16位就用空格补足为16位,
    # 如果大于16当时不是16的倍数,那就补足为16的倍数。
    def encrypt(self, text):
        text = text.encode('utf-8')
        cryptor = AES.new(self.key, self.mode, self.iv)
        # 这里密钥key 长度必须为16(AES-128),
        # 24(AES-192),或者32 (AES-256)Bytes 长度
        # 目前AES-128 足够目前使用
        length = 16
        count = len(text)
        if count < length:
            add = (length - count)
            # \0 backspace
            text = text + ('\0' * add).encode('utf-8')
        elif count > length:
            add = (length - (count % length))
            text = text + ('\0' * add).encode('utf-8')
        self.ciphertext = cryptor.encrypt(text)
        # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
        # 所以这里统一把加密后的字符串转化为16进制字符串
        return b2a_hex(self.ciphertext)

    # 解密后,去掉补足的空格用strip() 去掉
    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt(a2b_hex(text))
        return bytes.decode(plain_text).rstrip('\0')



if __name__ == '__main__':
    aes_key = 'ew19jvgm5wangkbu'
    pc = PrpCrypt(aes_key)  # 初始化密钥
    data = "xxx123"
    print("原始data: ", data)
    print("--------------第1种方法符合服务端的AES对称加密算法: ")
    e1 = AESUtil.encrypt(data, aes_key)
    d1 = AESUtil.decrypt(e1, aes_key)
    print("加密:", e1)
    print("解密:", d1)

    print("--------------第2种方法不符合服务端的AES对称加密算法: ")
    e2 = pc.encrypt(data)  # 加密
    d2 = pc.decrypt(e2).encode()  # 解密
    print("加密:", e2)
    print("解密:", d2)
utils/block_crypt.py
import json
import urllib3

import requests

from utils import block_crypt


def block_users(block_url: str, aes_key: str, block_user_ids: list,request_encrypt=False):
    headers = {
        'Content-Type': 'application/json'
    }
    # 请求体的参数是固定的 一些服务operator需要传
    request_payload = json.dumps({
        "operator": "gap1",
        "reason": "gap1",
        "ids": block_user_ids,
        "id_type": "uid",
    })

    aes_text = block_crypt.AESUtil.encrypt(request_payload, aes_key)
    print("加密的aes_text: ", aes_text)

    # 发送封禁请求 需要判断一下是否发送加密请求
    # 禁用warning
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    if request_encrypt:
        res = requests.post(block_url, data=aes_text, headers=headers, verify=False)
    else:
        res = requests.post(block_url, data=request_payload, headers=headers, verify=False)
    print("res: ", res, type(res), res.text)
    if request_encrypt:
        # 响应解密
        res_dec = block_crypt.AESUtil.decrypt(res.text, aes_key)
        print("res_dec: ", res_dec)
        res_json = json.loads(res_dec)
        print("封禁接口返回结果res_json: ", res_json, type(res_json))
        code = res_json.json().get("code")
        res_data = res_json.get("data")
        if res_data is None:
            print("返回的data是个None!!!!!")
            return

if __name__ == '__main__':
    block_url = "https://xxx-xxxice.xx.com/a/b"
    aes_key = "xxxxxxxxxxxxxxxx"
    user_ids = ["xxx","xx222"]
    block_users(block_url, aes_key, user_ids)
utils/block_request.py

~~~

posted on 2022-07-14 11:51  江湖乄夜雨  阅读(511)  评论(0编辑  收藏  举报