package com.logosdata.security.util; import com.alibaba.fastjson.JSONObject; import com.logosdata.security.SM2; import com.logosdata.security.SM3; import com.logosdata.security.SM4; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.math.ec.ECPoint; import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; import java.math.BigInteger; import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * {@code SignUtils} 签名工具类 * * @author Hengchen.Sun * @version 1.0.0 * @date 2021-02-18 * @since ver.1.0.0 */ @Slf4j public final class SignUtils { private SignUtils(){} /** * 通用解密方法 * @param json * @param secretKey * @return * @throws Exception */ public static String decryptData(String json, String secretKey) throws Exception { JSONObject jsonObject = JSONObject.parseObject(json); String decData = null; SM4 sm4 = new SM4(); sm4.setSecretKey(secretKey); sm4.setHexString(false); // 响应业务报文data String dataString =jsonObject.getString("data"); decData = sm4.decryptDataToString_ECB(dataString, "UTF-8"); // 响应签名sign String signString = jsonObject.getString("sign"); byte[] sign = Base64.getDecoder().decode(signString.getBytes()); Object signature1 =toObject(sign); log.info("签名:" + signature1.toString()); String[] arr = signature1.toString().split(","); BigInteger r = new BigInteger(arr[0], 16); BigInteger s = new BigInteger(arr[1], 16); SM2.Signature signature = new SM2.Signature(r, s); System.err.println(signature); // sm2加密 SM2 sm2 = new SM2(); // 读取公钥 ECPoint publicKey = sm2.importPublicKey(getConfigPublicKey().get("publicKey").toString()); String IDA = "taxhelper"; log.info("签名信息:" + decData); byte[] hash = SM3.hash(decData.getBytes("UTF-8")); // 验签 boolean flag = sm2.verify(new String(hash), signature, IDA, publicKey); System.out.println(flag); if (flag) { log.info("验证签名成功"); return decData; } else { log.info("验证签名失败"); // String errorMsg = "{\"message\":\"验证签名失败\"}"; String errorMsg = "验证签名失败"; throw new RuntimeException(errorMsg); } } /** * 通用加密方法 * @param param * @param secretKey * @return * @throws Exception */ public static Map encryptData(Map param, String secretKey) throws Exception { Map newParam = new HashMap<>(); JSONObject jsonObject = new JSONObject(); jsonObject.putAll(param); String decData = jsonObject.toString(); SM4 sm4 = new SM4(); // 加密密钥,由双方协定产生 sm4.setSecretKey(secretKey); sm4.setHexString(false); log.info("ECB模式加密"); String encData = sm4.encryptDataToString_ECB(decData, "UTF-8"); log.info("密文: " + encData); byte[] hash = SM3.hash(decData.getBytes("UTF-8")); SM2 sm2 = new SM2(); ECPoint publicKey = sm2.importPublicKey(getConfigPublicKey().get("publicKey").toString()); byte[] sign = sm2.encrypt(hash, publicKey); newParam = new HashMap<>(); newParam.put("data", encData); newParam.put("sign", Base64.getEncoder().encodeToString(sign)); log.info("data:" + encData); log.info("sign:" + Base64.getEncoder().encodeToString(sign)); return newParam; } public static Object toObject(byte[] bytes) throws Exception { Object obj = null; try { // bytearray to object ByteArrayInputStream bi = new ByteArrayInputStream(bytes); ObjectInputStream oi = new ObjectInputStream(bi); obj = oi.readObject(); log.error("签名对象:", obj); bi.close(); oi.close(); } catch (Exception e) { System.out.println("translation" + e.getMessage()); e.printStackTrace(); } return obj; } public static Map getConfigPublicKey() { Map map = new HashMap(); Properties props = System.getProperties(); // 获得系统属性集 String osName = props.getProperty("os.name").toLowerCase(); // 操作系统名称 if (osName.indexOf("linux") != -1 || osName.indexOf("unix") != -1) { // map.put("publicKey", "/home/logos/dzdk-api-gateway/publickey.pem"); // map.put("privateKey", "/home/logos/dzdk-api-gateway/privatekey.pem"); // map.put("publicKey", "/opt/wmproject/SBY-Secret/publickey.pem"); // map.put("privateKey", "/opt/wmproject/SBY-Secret/privatekey.pem"); map.put("publicKey", "/excel/publickey.pem"); map.put("privateKey", "/excel/privatekey.pem"); } if (osName.indexOf("mac") != -1){ map.put("publicKey", "/Users/jimmy/Develops/publickey.pem"); map.put("privateKey", "/Users/xuqiqi/IdeaProjects/logos/dzdk-api-gateway/privatekey.pem"); } if (osName.indexOf("windows") != -1) { // 开发测试 map.put("publicKey", "D:/publickey.pem"); map.put("privateKey", "D:/常用文本文件/代征代扣/封装接口资料/开发测试环境密钥/privatekey.pem"); // // 生产 // map.put("publicKey", "D:/常用文本文件/代征代扣/封装接口资料/生产环境密钥/publickey.pem"); // map.put("privateKey", "D:/常用文本文件/代征代扣/封装接口资料/生产环境密钥/privatekey.pem"); } return map; } }