OpenApi请求体加密

加密说明:

  • 采取主动使用加密的策略,当需要对openApi接口进行加密时需在请求头中增加加密类型securityType,例如securityType=AES,只有请求头中增加加密类型的接口才会采取对应类型的加密策略。
  • 除了【单点登录SSO】【企业openApi登陆】接口,其余接口都会对返回数据进行整体加密
  • 加密策略:先对返回的数据进行AES加密,然后再进行base64编码,即可得到加密后的数据
  • 解密策略:先对加密数据进行base64解码,然后AES解密

时序图:

时序图
Figure: 时序图

秘钥处理逻辑说明

从每刻获取的密钥需通过特殊处理后方可正常使用,具体操作如下:

String key = new String(Arrays.copyOf(Base64.encodeBase64String("{从每刻获取的密钥}".getBytes()).getBytes(), 16))

加解密工具AESUtil:

package com.maycur.common.util;

import com.maycur.common.constant.I18NMessage;
import com.maycur.common.exception.NAckException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class AESUtil {

    private static final String TRANSFORM_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
    private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);

    /**
     * 基于CBC工作模式的AES加密
     *
     * @param value 待加密字符串
     * @param key   秘钥
     */
    public static String encryptCbcMode(final String value, String key) {
        if (StringUtils.isNotBlank(value)) {

            final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");

            //初始化向量器
            final IvParameterSpec ivParameterSpec = new IvParameterSpec(Arrays.copyOfRange(key.getBytes(), 0, 16));

            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_CBC_PKCS5);

                //加密模式
                encipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
                //使用AES加密
                byte[] encrypted = encipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
                //然后转成BASE64返回
                return Base64.encodeBase64String(encrypted);
            } catch (Exception e) {
                logger.warn("使用AES加密失败, errorMsg:{}", e.getMessage(), e);
                throw new NAckException(I18NMessage.MESSAGE_ENT_SECRET_ENCRYPT);
            }
        }
        return value;
    }

    /**
     * 基于CBC工作模式的AES解密
     *
     * @param encryptedStr AES加密之后的字符串
     * @param key          秘钥
     */
    public static String decryptCbcMode(final String encryptedStr, String key) {
        if (StringUtils.isNotBlank(encryptedStr)) {
            final SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            //初始化向量器
            final IvParameterSpec ivParameterSpec = new IvParameterSpec(Arrays.copyOfRange(key.getBytes(), 0, 16));

            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_CBC_PKCS5);

                //设定加密模式
                encipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
                //用BASE64解密
                byte[] encryptedBytes = Base64.decodeBase64(encryptedStr);
                //用AES解密
                byte[] originalBytes = encipher.doFinal(encryptedBytes);

                return new String(originalBytes);
            } catch (Exception e) {
                logger.warn("使用AES解密失败, errorMsg:{}", e.getMessage(), e);
                throw new NAckException(I18NMessage.MESSAGE_ENT_SECRET_DECRYPT);
            }
        }
        return null;
    }

    public static void main(String[] args) {

        String value = "{\"test\":\"测试待加密数据\"}";

        byte[] bytes = Arrays.copyOf(Base64Utils.encodeToString("DTEC180818128U4MCS".getBytes()).getBytes(), 16);

        String key = new String(bytes);
        System.out.println(key);
        System.out.println(key.getBytes().length);
        String encryptValue = encryptCbcMode(value, key);

        System.out.println(encryptValue);

        String decryptValue = decryptCbcMode(encryptValue, key);

        System.out.println(decryptValue);
    }

    public static void main(String[] args) {

        String value = "{\n" +
                "    \"length\": 100,\n" +
                "    \"start\": 200,\n" +
                "    \"keyword\": \"\"\n" +
                "}";

                //"DTEC180818128U4MCS" 配置的密钥
        byte[] bytes = Arrays.copyOf(Base64Utils.encodeToString("DTEC180818128U4MCS".getBytes()).getBytes(), 16);

                //实际加密使用的密钥
        String key = new String(bytes);
        System.out.println(key);
        System.out.println(key.getBytes().length);
        String encryptValue = encryptCbcMode(value, key);

        System.out.println(encryptValue);

        String decryptValue = decryptCbcMode(encryptValue, key);

        System.out.println(decryptValue);
    }
}
Copyright © 杭州每刻科技有限公司 www.maycur.com all right reserved,powered by Gitbook该文件修订时间: 2024-11-20 10:52:00

results matching ""

    No results matching ""

    results matching ""

      No results matching ""