You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
6.3 KiB

3 years ago
/*
* Copyright (C), 2015-2019
* FileName: FuncUtils
* Author: xx
* Date: 2019/8/22 15:05
* Description: FuncUtils
* History:
* <author> <time> <version> <desc>
*/
package com.fr.plugin.tabledataservice.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import com.fanruan.api.json.JSONKit;
import com.fr.base.Icon;
import com.fr.base.IconManager;
import com.fr.data.NetworkHelper;
import com.fr.general.ComparatorUtils;
import com.fr.general.IOUtils;
import com.fr.io.utils.MD5Calculator;
import com.fr.json.JSONObject;
import com.fr.locale.InterProviderFactory;
import com.fr.plugin.tabledataservice.ConfigTableDataService;
import com.fr.web.utils.WebUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.*;
import static com.fr.plugin.tabledataservice.Constants.ICON_PATH;
/**
* Function Description<br>
* FuncUtils
*
* @author xx
* @since 1.0.0
*/
public class FuncUtils {
static {
//如果是PKCS7Padding填充方式,则必须加上下面这行
Security.addProvider(new BouncyCastleProvider());
}
/**
* 数据加密和签名
*
* @param bizData 业务数据
* @param result
* @return
*/
public static void encryptData(String bizData, JSONObject result) {
//弹性平台sm2公钥
String iqbPublicKey = ConfigTableDataService.getInstance().getIqbPublicKey();
//可视化sm2私钥
String visualPrivateKey = ConfigTableDataService.getInstance().getVisualPrivateKey();
//可视化appId
String appId = ConfigTableDataService.getInstance().getVisualAppId();
String aesPw = RandomUtil.randomString(16);//明文sm4key
String aesIv = RandomUtil.randomString(16); //sm4iv
//对请求参数 sm4加密
String encryptData = sm4Encrypt(bizData, aesPw, aesIv);
//对明文aesPw sm2加密
String key = sm2Encrypt(aesPw, iqbPublicKey);
//组装请求参数
HashMap<String, Object> encryptReqMap = new HashMap<>();
encryptReqMap.put("appId", appId);
encryptReqMap.put("time", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
encryptReqMap.put("data", encryptData);
encryptReqMap.put("key", key);
encryptReqMap.put("iv", aesIv);
encryptReqMap.put("requestNo", IdUtil.getSnowflake(2, 1).nextIdStr() + IdUtil.getSnowflake(2, 1).nextIdStr());
//获取待签名请求参数并用可视化私钥签名
String waitSign = getSignContent(encryptReqMap);
String signature = sign(waitSign, visualPrivateKey);
//签名附加到请求参数
result.put("appId", encryptReqMap.get("appId"));
result.put("time", encryptReqMap.get("time"));
result.put("data", encryptReqMap.get("data"));
result.put("key", encryptReqMap.get("key"));
result.put("iv", encryptReqMap.get("iv"));
result.put("requestNo", encryptReqMap.get("requestNo"));
result.put("sign", signature);
}
//SM2非对称加密
private static String sm2Encrypt(String data, String publicKey) {
return new SM2(null, publicKey).encryptBase64(data, KeyType.PublicKey);
}
//SM4对称加密
private static String sm4Encrypt(String bizData, String key, String iv) {
return cn.hutool.core.codec.Base64.encode(new SM4(Mode.CBC, Padding.PKCS5Padding, key.getBytes(), iv.getBytes()).encrypt(bizData));
}
//获取待签名数据
private static String getSignContent(HashMap<String, Object> paramMap) {
paramMap.remove("sign");
Map<String, Object> stringObjectMap = sortMapByKey(paramMap);
return JSONKit.create(stringObjectMap).encode();
}
/**
* 根据map的key进行字典升序排序
*
* @param map
* @return map
*/
private static Map<String, Object> sortMapByKey(Map<String, Object> map) {
Map<String, Object> treemap = new TreeMap<>(map);
List<Map.Entry<String, Object>> list = new ArrayList<>(treemap.entrySet());
list.sort(Map.Entry.comparingByKey());
return treemap;
}
// 签名
private static String sign(String data, String privateKey) {
return cn.hutool.core.codec.Base64.encode(new SM2(privateKey, null).sign(data.getBytes(StandardCharsets.UTF_8)));
}
/**
* MD5验证key报表路径时间戳计算
*
* @param appKey
* @param params
* @return
*/
public static Boolean validateMD5(String appKey, JSONObject params) {
StringBuffer str = new StringBuffer();
str.append(appKey);
str.append(params.getString("report_path"));
str.append(params.getString("timestamp"));
String token = MD5Calculator.calculateMD5(str.toString().getBytes());
return ComparatorUtils.equals(token, params.getString("sign"));
}
public static void printErrorJSON(HttpServletResponse res, int code) throws Exception {
JSONObject errorJSON = JSONObject.create();
errorJSON.put("err_code", code)
.put("err_msg", InterProviderFactory.getProvider().getLocText("Plugin-tabledataservice_Error_" + code));
WebUtils.printAsJSON(res, errorJSON);
}
public static JSONObject getParams(HttpServletRequest req) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(NetworkHelper.getRequestInputStream(req), "utf-8"));
StringBuilder sb = new StringBuilder();
String temp;
while ((temp = br.readLine()) != null) {
sb.append(temp);
}
br.close();
return new JSONObject(sb.toString());
}
public static String loadIcon() {
Icon icon = new Icon("json", IOUtils.readImage(ICON_PATH));
IconManager.getIconManager().addIcon(icon, true);
return icon.getName();
}
}