接口测试 Python/Java AES 加解密方法互相转换

Charseki.Chen · 2020年09月08日 · 656 次阅读

背景介绍

公司的接口有签名校验,请求头中包含了请求的时间戳,所以这种接口必须动态入参,否则无法请求成功。

之前直接调用开发的工具类 jar 包接口,可最近公司三天两头停电,服务器老挂。。。把我整懵逼了。

网上找了一堆,发现加密出来的都不一样,,最终决定自己去实现个 Python 版的 AES 加/解密方法。

层层加密方法嵌套中,最为棘手的就是 AES 加/解密的方法。

倒不是说 AES 本身加密方法有多复杂,而是两种 IDE 的 AES 第三方包存在小部分差异。

Java 中 AES 加/解密的填充方式是封装过的,而 Python 的 AES 就需要自己去定义填充方式。

查看了 Java 的 AES 封装方法的源代码,发现默认采用是 pack5padding 的填充方式。

在知道原理后,其实用 Python 去构造这种填充方式并不难。

# -*- coding: utf-8 -*-
"""
@File:blog_test_code.py    
@E-mail:364942727@qq.com
@Time:2020/9/8 10:08 下午 
@Author:Nobita   
@Version:1.0   
@Desciption:Java AES  <---> Python AES
"""

import base64
import requests
from Crypto.Cipher import AES
from urllib import parse


class MyHash(object):
    def __init__(self):
        """
        :param mode: AES加密模式
        """
        self.mode = AES.MODE_ECB

    def My_Aes_Encrypt(self, key, msg):
        """
        Aes 算法加密 ( MODE = AES.MODE_ECB;无VI偏移量;)
        :param key: 需加密的密钥
        :param msg: 需加密的字符串
        :return:
        """
        self.key = key
        self.BS = len(key)
        self.pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS)
        Cryptor = AES.new(self.key.encode("utf8"), self.mode)
        self.ciphertext = Cryptor.encrypt(bytes(self.pad(msg), encoding="utf8"))
        # AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题,使用base64编码
        bin_encrypt_result = base64.b64encode(self.ciphertext)  # 输出的是二进制Unicode编码
        return bin_encrypt_result.decode('utf8')

    def My_Aes_Decrypt(self, key, msg):
        """
        Aes 算法解密 ( MODE = AES.MODE_ECB;无VI偏移量;)
        :param key: 需解密的密钥
        :param msg: 需解密的字符串
        :return:
        """
        self.key = key
        self.BS = len(key)
        self.unpad = lambda s: s[0:-ord(s[-1:])]
        decode = base64.b64decode(msg)
        Cryptor = AES.new(self.key.encode("utf8"), self.mode)
        self.plain_text = Cryptor.decrypt(decode)
        bin_decrypt_result = self.unpad(self.plain_text)  # 输出的是二进制Unicode编码
        return bin_decrypt_result.decode('utf8')

    def My_Aes(self, key, msg):
        """
        Java 加/解密工具类接口
        :param key: 需加密的密钥
        :param msg: 需加密的字符串
        :return: 加密后的字符
        """
        # 调用本地AES_jar包接口
        url = 'http://127.0.0.1:4271/aes/encrypt'
        payload = {
            "psw": key,
            "content": msg
        }
        r = requests.post(url=url, data=payload)
        res = r.json()['Data']
        return res


helo = MyHash()

if __name__ == '__main__':
    print('--------------------------------------Python-AES加/解密部分--------------------------------------')
    Aes_Key = "WuMlCJRN8zO886dw"
    Aes_Encrypt_msg = "<FPXX><NSRSBH>330201999999868</NSRSBH><DDLSH>3302019999998684221</DDLSH></FPXX><FPXX><NSRSBH>330201999999868</NSRSBH>330201999999868</NSRSBH>"
    res_Aes_Encrypt = helo.My_Aes_Encrypt(Aes_Key, Aes_Encrypt_msg)
    print('Aes加密前字符串:{},\nAes加密结果:{}'.format(Aes_Encrypt_msg, res_Aes_Encrypt))
    Aes_Decrypt_msg = "hhCWnmDtU1NxQlXiE+LMiRozGLJpbu2P/2hraeHuWUQdSUtwMmwlRlPzIJqI+lbilCOe9NU3jCm6ZcelKH3eaUie36oiU4X8S94ujyhlP/qL9mKXl4oqlQo+jZzvR2DnMn45V7v3dMQ21D97sdZQvB12t9W/O2wDzBMoKKBcqIeWiJybq/MSoGBkrmOzvs1F"
    res_Aes_Decryot = helo.My_Aes_Decrypt(Aes_Key, Aes_Decrypt_msg)
    print('Aes解密前字符串:{},\nAes解密解果:{}'.format(Aes_Decrypt_msg, res_Aes_Decryot))
    print('--------------------------------------Java工具类-AES加/解密部分--------------------------------------')
    Java_Encrypt_result = helo.My_Aes(Aes_Key, Aes_Encrypt_msg)
    print('Java Aes加密接口加密后的结果:{}'.format(Java_Encrypt_result))

从代码中,我们清晰的能看到,我拿自己用 Python 写的 AES 加/解密算法和本地的 api 调用接口在进行比较。

这个 api 接口是一个工具类 jar 包,关于 AES 加/解密算法的。

下面附上 Pycharm 运行结果图:

为了比较结果更加直观,再贴一张 Beyond Compare 的对比图:

共收到 0 条回复 时间 点赞
Charseki.Chen 关闭了讨论 10月02日 01:34
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册