1.Hutool参考文档
https://www.hutool.cn/
2.系统交互流程
注意:并非所有的公司都是以下流程,每个公司加密、加签顺序,以及加密、加签的字段都可能不同,以下交互图,以及代码示例只是某公司场景,具体问题具体分析
3.DEMO示例
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.tomcat.util.codec.binary.Base64;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* TestGw
*
* @author: z
* @date: 2022/5/17 13:36
*/
public class TestGw {
// 己方私钥
private static String PRIVATE_KEY = "MIIJQwIBADANBgkqhkiG";
// 合作方公钥
private static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0B";
private static String local_url = "http://localhost:8080/service/123";
static class GsonUtil {
static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
public static String toJsonString(Object obj) {
return gson.toJson(obj);
}
public static Map<String, Object> fromJson2Map(String obj) {
TypeToken<Map<String, Object>> mapTypeToken = new TypeToken<Map<String, Object>>() {};
return fromJson2Type(obj, mapTypeToken);
}
public static <T> T fromJson2Type(String obj, TypeToken typeToken) {
return gson.fromJson(obj, typeToken.getType());
}
}
public static void main(String[] args) {
// 业务参数
Map<String, Object> bizMap = new HashMap<>();
bizMap.put("mobile", "15311281112");
bizMap.put("certNo", "130625199210101010");
bizMap.put("name", "张三");
bizMap.put("channelNo", "2865010");
// 网关请求
HashMap<String, Object> map = new HashMap<>();
map.put("appKey", "xxxxxxxxxx");
map.put("serviceName", "xxxxxxxxx");
map.put("bizContent", encryptedByPubKey(bizMap));
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
map.put("timestamp", sdf.format(new Date()));
map.put("format", "json");
map.put("signType", "RSA");
map.put("charset", "UTF-8");
map.put("version", "1.0.0");
map.put("sign", signByPriKey(map));
// 发送请求
System.out.println("请求入参:" + GsonUtil.toJsonString(map));
String resp = HttpUtil.createPost(local_url)
.body(GsonUtil.toJsonString(map), ContentType.JSON.toString())
.execute()
.body();
System.out.println("请求出参:" + resp);
// 验签
if (!checkSignByPubKey(GsonUtil.fromJson2Map(resp))) {
System.out.println("签名错误");
return;
}
// 解密
String bizContents = decryptByPriKey(resp);
System.out.println("解密:" + bizContents);
}
/**
* 合作方返回结果时,会用我方公钥加密
* 我们收到返回结果时,用我方私钥解密
*/
private static String decryptByPriKey(String resp) {
RSA rsa = new RSA(PRIVATE_KEY, null);
Map<String, Object> map1 = GsonUtil.fromJson2Map(resp);
return rsa.decryptStr(map1.get("bizContent").toString(), KeyType.PrivateKey);
}
/**
* 合作方返回结果时,会用合作方私钥加签
* 我们收到返回结果时,用合作方公钥验签
*/
private static boolean checkSignByPubKey(Map<String, Object> respMap) {
String signValue = (String) respMap.get("sign");
respMap.remove("sign");
String s = GsonUtil.toJsonString(respMap);
Sign sign = new Sign(SignAlgorithm.SHA1withRSA, null, PUBLIC_KEY);
return sign.verify(s.getBytes(StandardCharsets.UTF_8), Base64.decodeBase64(signValue.getBytes(StandardCharsets.UTF_8)));
}
/**
* 合作方公钥加密
* 合作方收到请求后,用合作方私钥解密
*/
private static Object encryptedByPubKey(Map<String, Object> bizMap) {
TreeMap<String, Object> sort = MapUtil.sort(bizMap);
String sortJson = GsonUtil.toJsonString(sort);
RSA pubRsa = new RSA(null, PUBLIC_KEY);
byte[] encryptedData = pubRsa.encrypt(sortJson.getBytes(StandardCharsets.UTF_8), KeyType.PublicKey);
return Base64.encodeBase64String(encryptedData);
}
/**
* 己方私钥加签
* 合作方收到请求后,用我方公钥验签
*/
public static String signByPriKey(Map<String, Object> params) {
TreeMap<String, Object> sort = MapUtil.sort(params);
String paramsJson = GsonUtil.toJsonString(sort);
Sign sign = new Sign(SignAlgorithm.SHA1withRSA, PRIVATE_KEY, null);
return Base64.encodeBase64String(sign.sign(paramsJson.getBytes(StandardCharsets.UTF_8)));
}
}