java实现接口测试中AES加密后Base64加密请求体数据

加密规则

请求体采用 AES(AES-GCM-256) 加密方式,AES 加密需申请 Key 和 IV,
请求时,先用 AES 加密,再用 Base64 对请求体的 data 内容进行加密
对于无法正常解密的,将返回code 状态码500。

代码实现

目录结构

.
├── AESJiami.iml
├── lib
│   ├── bcprov-ext-jdk15to18-177.jar
│   └── core-1.53.0.0.jar
├── out
│   └── production
│       └── AESJiami
│           └── com
│               └── chenguoxin
│                   ├── AES.class
│                   └── AESJIami.class
├── readme.md
└── src
    └── com
        └── chenguoxin
            ├── AES.java
            └── AESJIami.java

具体代码

AESJiami.java

package com.chenguoxin;

import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.DataLengthException;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

public class AESJIami {
    public static final int NONCE_BIT_SIZE = 128;
    public static final int MAC_BIT_SIZE = 128;
    public static final int KEY_BIT_SIZE = 256;
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();

    /**
     * 创建密钥
     * * @return 密钥
     */
    public static byte[] key() {
        byte[] key = new byte[KEY_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(key);
        return key;
    }

    /**
     * 创建向量
     *
     * @return 向量
     */
    public static byte[] iv() {
        byte[] iv = new byte[NONCE_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(iv);
        return iv;
    }

    /**
     * 编码
     *
     * @param hexStr 文本
     * @return 字节数组
     */
    public static byte[] hexToByte(String hexStr) {
        int len = hexStr.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4) + Character.digit(hexStr.charAt(i + 1), 16));
        }
        return data;
    }

    /**
     * 转为十六进制
     *
     * @param data 字节数组
     * @return 转换结果
     */
    public static String toHex(byte[] data) {
        StringBuilder ret = new StringBuilder();
        for (byte datum : data) {
            String hex = Integer.toHexString(datum & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret.append(hex.toUpperCase());
        }
        return ret.toString();
    }

    /**
     * 加密
     *
     * @param plainText 明文文本
     * @param key       密钥
     * @param iv        向量
     * @return 加密字符串
     */
    public static String encrypt(String plainText, byte[] key, byte[] iv) {
        String sr;
        try {
            byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
            GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
            AEADParameters parameters = new AEADParameters(new KeyParameter(key), MAC_BIT_SIZE, iv, null);
            cipher.init(true, parameters);
            byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
            int retLen = cipher.processBytes(plainBytes, 0, plainBytes.length, encryptedBytes, 0);
            cipher.doFinal(encryptedBytes, retLen);
            sr = Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }
        return sr;
    }

    /**
     * 解密
     *
     * @param encryptedText 已加密文本
     * @param key           密钥
     * @param iv            向量
     * @return 已解密文本
     */
    public static String decrypt(String encryptedText, byte[] key, byte[] iv) {
        String sr;
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
            GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
            AEADParameters parameters = new AEADParameters(new KeyParameter(key), MAC_BIT_SIZE, iv, null);
            cipher.init(false, parameters);
            byte[] plainBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
            int retLen = cipher.processBytes(encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
            cipher.doFinal(plainBytes, retLen);
            sr = new String(plainBytes, StandardCharsets.UTF_8);
        } catch (IllegalArgumentException | IllegalStateException | DataLengthException |
                 org.bouncycastle.crypto.InvalidCipherTextException ex) {
            throw new RuntimeException(ex.getMessage());
        }
        return sr;
    }

}

AES.java

package com.chenguoxin;

public class AES {
        public static String Jiami(String mingwen, byte[] key, byte[] iv) {
        return AESJIami.encrypt(mingwen, key, iv);
    }

}

BeanShell脚本

import com.chenguoxin.AES;

String mingwen = "nihao"; //需要加密的明文

byte[] key = { };//例如byte[] key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }

byte[] iv = { };//例如byte[] iv = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }

String miwen = AES.Jiami(mingwen,key,iv);

vars.put("miwen", miwen);//设置密文为全局变量

遇到的坑

写完脚本打完jar包后上传到metersphere平台测试,发现只要一调用这个jar包里面的方法,接口也不会请求了,也没有报错信息,在一番查找问题过后发现是因为使用的 JMeter 版本只支持 Java 运行时的类文件版本到 52.0,而您编译的类文件版本为 62.0,因此导致无法识别。您需要升级 JMeter 或者降低 Java 编译的类文件版本以解决这个问题。
写代码用的mac的开发环境和使用jar包的环境版本不匹配。。可恶的是metersphere平台没有任何报错信息,还是在jmeter中使用beanshell取样器查看到的报错信息。

JAVA接口测试自动化测试

Java实现登录接口在redis中根据key值获取验证码

2023-6-27 18:25:11

网络攻防

通过mysql编码 以hex字符串注入方法

2023-3-29 14:28:55

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索