|
@@ -0,0 +1,254 @@
|
|
|
|
|
+package com.sckw.core.utils;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.sckw.core.model.constant.Global;
|
|
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
|
+import org.bouncycastle.util.encoders.Hex;
|
|
|
|
|
+import javax.crypto.Cipher;
|
|
|
|
|
+import javax.crypto.KeyGenerator;
|
|
|
|
|
+import javax.crypto.SecretKey;
|
|
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
|
|
+import java.security.Key;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * @create 2019-02-27
|
|
|
|
|
+ * @description 加密工具类
|
|
|
|
|
+ */
|
|
|
|
|
+public class EncryUtil {
|
|
|
|
|
+ /**可调用EncryUtil.generatorPriKey()方法生成*/
|
|
|
|
|
+ public static final String PRI_KEY = "127f0400ff8a8b7a20d91dfc60a39725";
|
|
|
|
|
+ /**API签名铭文*/
|
|
|
|
|
+ public static final String SIGN_KEY = "sign";
|
|
|
|
|
+ /**API签名公钥*/
|
|
|
|
|
+ public static final String ACCESS_KEY = "accessKey";
|
|
|
|
|
+ /**API签名私钥*/
|
|
|
|
|
+ public static final String ACCESS_SECRET = "accessSecret";
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 私钥生成器
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String generatorPriKey() throws Exception{
|
|
|
|
|
+ //生成Key
|
|
|
|
|
+ KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
|
|
|
|
+ keyGenerator.init(128);
|
|
|
|
|
+ SecretKey secretKey = keyGenerator.generateKey();
|
|
|
|
|
+ byte[] keyBytes = secretKey.getEncoded();
|
|
|
|
|
+ String priKey = toHexString(keyBytes);
|
|
|
|
|
+ return priKey;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 加密
|
|
|
|
|
+ * @param appSecret 私钥
|
|
|
|
|
+ * @param orginStr 原始加密参数
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String encry(String appSecret, String orginStr) throws Exception{
|
|
|
|
|
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
|
|
|
|
+ Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
|
|
|
|
|
+ cipher.init(Cipher.ENCRYPT_MODE, key);
|
|
|
|
|
+ byte[] encodeResult = cipher.doFinal(orginStr.getBytes());
|
|
|
|
|
+ return Hex.toHexString(encodeResult);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 加密
|
|
|
|
|
+ * @param appSecret 私钥
|
|
|
|
|
+ * @param jsonObject 原始加密参数
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String encry(String appSecret, JSONObject jsonObject) throws Exception{
|
|
|
|
|
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
|
|
|
|
+ Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
|
|
|
|
|
+ cipher.init(Cipher.ENCRYPT_MODE, key);
|
|
|
|
|
+ byte[] encodeResult = cipher.doFinal(jsonObject.toJSONString().getBytes());
|
|
|
|
|
+ return Hex.toHexString(encodeResult);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 字节数组转成16进制表示格式的字符串
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String toHexString(byte[] byteArray) {
|
|
|
|
|
+ if (byteArray == null || byteArray.length < 1){
|
|
|
|
|
+ throw new IllegalArgumentException("this byteArray must not be null or empty");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ final StringBuilder hexString = new StringBuilder();
|
|
|
|
|
+ for (int i = 0; i < byteArray.length; i++) {
|
|
|
|
|
+ if ((byteArray[i] & 0xff) < 0x10){
|
|
|
|
|
+ hexString.append("0");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hexString.append(Integer.toHexString(0xFF & byteArray[i]));
|
|
|
|
|
+ }
|
|
|
|
|
+ return hexString.toString().toLowerCase();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16进制的字符串表示转成字节数组
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static byte[] toByteArray(String hexString) {
|
|
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isEmpty(hexString)){
|
|
|
|
|
+ throw new IllegalArgumentException("this hexString must not be empty");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hexString = hexString.toLowerCase();
|
|
|
|
|
+ final byte[] byteArray = new byte[hexString.length() / 2];
|
|
|
|
|
+ int k = 0;
|
|
|
|
|
+ //因为是16进制,最多只会占用4位,转换成字节需要两个16进制的字符,高位在先
|
|
|
|
|
+ for (int i = 0; i < byteArray.length; i++) {
|
|
|
|
|
+ byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
|
|
|
|
|
+ byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
|
|
|
|
|
+ byteArray[i] = (byte) (high << 4 | low);
|
|
|
|
|
+ k += 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ return byteArray;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解密
|
|
|
|
|
+ * @param appSecret 私钥
|
|
|
|
|
+ * @param encryStr 加密了的字符串
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public synchronized static String descry(String appSecret, String encryStr) throws Exception {
|
|
|
|
|
+ Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
|
|
|
|
|
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
|
|
|
|
+ cipher.init(Cipher.DECRYPT_MODE, key);
|
|
|
|
|
+ byte[] decodeResult = cipher.doFinal(org.apache.commons.codec.binary.Hex.decodeHex(encryStr));
|
|
|
|
|
+ return new String(decodeResult);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解密
|
|
|
|
|
+ * @param appSecret 私钥
|
|
|
|
|
+ * @param encryStr 加密了的字符串
|
|
|
|
|
+ * @author dengyinghui
|
|
|
|
|
+ * #date 2019/02/27
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static JSONObject descryJson(String appSecret, String encryStr) throws Exception {
|
|
|
|
|
+ String json = EncryUtil.descry(Global.PRI_KEY, encryStr);
|
|
|
|
|
+ return JSON.parseObject(json);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @description 校验
|
|
|
|
|
+ * @author zk
|
|
|
|
|
+ * @date 2020/8/15 15:15
|
|
|
|
|
+ * @param
|
|
|
|
|
+ * @return
|
|
|
|
|
+ **/
|
|
|
|
|
+ public static boolean checkSign(Map<String, Object> data, String accessSecret) {
|
|
|
|
|
+ String originSign = null;
|
|
|
|
|
+ Map params = CollectionUtils.createHashMap();
|
|
|
|
|
+ for (Map.Entry<String, Object> entry : data.entrySet()) {
|
|
|
|
|
+ if (SIGN_KEY.equals(entry.getKey())){
|
|
|
|
|
+ originSign = StringUtils.objectStr(entry.getValue());
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ACCESS_KEY.equals(entry.getKey())){
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ params.put(entry.getKey(), entry.getValue());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String sign = createSign(params, accessSecret);
|
|
|
|
|
+ return sign.equals(originSign);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @description 校验
|
|
|
|
|
+ * @author zk
|
|
|
|
|
+ * @date 2020/8/17 17:45
|
|
|
|
|
+ * @param
|
|
|
|
|
+ * @return
|
|
|
|
|
+ **/
|
|
|
|
|
+ public static boolean checkSign(HttpServletRequest request, String accessSecret) {
|
|
|
|
|
+ Enumeration<?> pNames = request.getParameterNames();
|
|
|
|
|
+ Map<String, Object> params = new HashMap<String, Object>();
|
|
|
|
|
+ while (pNames.hasMoreElements()) {
|
|
|
|
|
+ String pName = (String) pNames.nextElement();
|
|
|
|
|
+ if (SIGN_KEY.equals(pName)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ Object pValue = request.getParameter(pName);
|
|
|
|
|
+ params.put(pName, pValue);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return checkSign(params, accessSecret);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @description 生成签名
|
|
|
|
|
+ * @author zk
|
|
|
|
|
+ * @date 2020/8/15 15:14
|
|
|
|
|
+ * @param {params:请求参数,accessSecret 私钥}
|
|
|
|
|
+ * @return
|
|
|
|
|
+ **/
|
|
|
|
|
+ public static String createSign(Map<String, Object> params, String accessSecret) {
|
|
|
|
|
+ Set<String> keysSet = params.keySet();
|
|
|
|
|
+ Object[] keys = keysSet.toArray();
|
|
|
|
|
+ Arrays.sort(keys);
|
|
|
|
|
+ StringBuilder temp = new StringBuilder();
|
|
|
|
|
+ boolean first = true;
|
|
|
|
|
+ for (Object key : keys) {
|
|
|
|
|
+ if (first) {
|
|
|
|
|
+ first = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ temp.append("&");
|
|
|
|
|
+ }
|
|
|
|
|
+ temp.append(key).append("=");
|
|
|
|
|
+ Object value = params.get(key);
|
|
|
|
|
+ String valueString = "";
|
|
|
|
|
+ if (null != value) {
|
|
|
|
|
+ valueString = String.valueOf(value);
|
|
|
|
|
+ }
|
|
|
|
|
+ temp.append(valueString);
|
|
|
|
|
+ }
|
|
|
|
|
+ temp.append("&").append(ACCESS_SECRET).append("=").append(accessSecret);
|
|
|
|
|
+ //LogUtil.debug("参数:" + temp.toString());
|
|
|
|
|
+ return PasswordUtils.md5(temp.toString()).toUpperCase();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public static void main(String [] age) {
|
|
|
|
|
+ long timeStamp = System.currentTimeMillis();
|
|
|
|
|
+ Map<String, Object> params = CollectionUtils.createHashMap();
|
|
|
|
|
+ params.put("subtaskId", "SDT2008020000301");
|
|
|
|
|
+ params.put("goodsName", "工业级碳酸乙烯酯");
|
|
|
|
|
+ params.put("grossWeight", "47.7800");
|
|
|
|
|
+ params.put("netWeight", "17.6800");
|
|
|
|
|
+ params.put("weight", "30.0000");
|
|
|
|
|
+ params.put("timeStamp", "1597890005658");
|
|
|
|
|
+ String singStr = createSign(params, "xinyuan20200819");
|
|
|
|
|
+ System.out.println("sign:" +singStr);
|
|
|
|
|
+ System.out.println("timeStamp:" +timeStamp);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|