Commit a2ed5c70 authored by 赵啸非's avatar 赵啸非

添加国密4加解密接口

parent f0fd6959
package com.mortals.xhx.common.utils;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Cipher;
import java.net.URLDecoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class RSAUtils {
// 私钥
private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJJuFUH/4m9H5hCCzxtd9BxpjWlG9gbejqiJpV0XJKaU1V7xDBJasswxPY7Zc15RoxWClPoKPwKrbWKm49dgBJebJq5xd4sLCSbboxRkKxpRiJHMZ4LJjYa5h9Ei9RyfoUzqGHqH4UrDy3m3IwPiP19cIBqoU50shyQf92ZpcGZhAgMBAAECgYEAiadU8pODoUs82x6tZbPALQmJN4PO+wwznfqv6sA74yGdKECAMazz0oMjtGt1SiCCqFD2jcweCftvvELZg3mvNg1V0vRQRD1ZCA8HDp8DXm20d11K3+RX39tR4KgyyM3HsSEhkUDujMxKIpYjyiB5iEtV7Ja9bZ2fROszq+mUIqUCQQDQQf6vWRMLBqfnDcU77vuDGOhXbjkF2ytLxLW3fbKaW3GWvC3n93zPM+mcvWSXgkl448+jFjpMktm1Vn+w+YX3AkEAs/+bbRbod6AcVbLu8C5E44qDRoRpu+LF7Cphp8tlSAIRjm2yGP5acMWGRUtH9MF2QJYPF0PgDzdmUSVqWnCAZwJBALnSuRri4wAKn1SmT+ALfLZcSiyBODZGeppv2ijw6qWahH8YR+ncRaxoyMFHqPMbmM1akJIXqktbGREaLnPOIb8CQQCdJycJaL3Qa98xR4dr9cm5rF6PO96g5w6M8jfO6ztjUkMHymh7f99wpFRlvaN2Y06edyV315ARWPohEPy5N44zAkBlLuDHLm1TkTTAfdlL5r2OcdjpaJYloTdn05Mp3+J+w1zTX8k6Mz8lFZtLUcoMeTfQ9rm/+u2KwxS8NljtSZWH";
public static String decode(String encodeStr, String privateKey) {
String decodeStr = null;
try {
byte[] decodeHexStr = Hex.decodeHex(encodeStr.toCharArray());
privateKey = privateKey.replaceAll(" +", "+");
byte[] privateKeyByte = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory RSAKeyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = RSAKeyFactory.generatePrivate(privateKeySpec);
Cipher cipher = Cipher.getInstance(RSAKeyFactory.getAlgorithm());
cipher.init(2, key);
byte[] bytes = cipher.doFinal(decodeHexStr);
decodeStr = URLDecoder.decode(new String(bytes), "utf-8");
} catch (Exception e) {
System.out.println("RSAdecode error: " + e);
}
return decodeStr;
}
public static void main(String[] args) {
String content="130fddec666d6a60ca27ca64e36706d3ee52ee710795636db1fb15a564d2abef1aaa13ab86eaaf534dc4e5e39033f07206a69057519a9a85ecb987c8307dd2514fb6cebcb763c16630cd3941476bb02a96133333c3e8e3d7ebe2fdac0d478d5338d928a1048213b27de330e1c8cd6eea80543f9a12789ab078c4ce96008f242b";
System.out.println(RSAUtils.decode(content,PRIVATE_KEY));
}
}
package com.mortals.xhx.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.springframework.http.*;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
/**
* 服务集成平台调用工具类
*
* @author liuyang05
*/
@SuppressWarnings("unused")
@Data
public class ServicePlatformInvoker {
/**
* 成功调用标识
*/
private static final String SUCCESS = "1";
/**
* 默认版本号
*/
private static final String DEFAULT_VERSION = "1.0";
/**
* 请求地址
*/
private String url;
/**
* 接入标识
*/
private String accessKey;
/**
* 接入密钥
*/
private String privateKey;
/**
* 是否mock
*/
private boolean isMock;
/**
* 签名算法
*/
private SignAlgorithm signAlgorithm = SignAlgorithm.SM2;
private RestTemplate restTemplate = new RestTemplate();
/**
* 数据格式
*/
public enum DateFormat {
/**
* json
*/
JSON("json");
private String value;
DateFormat(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
/**
* 签名算法
*/
public enum SignAlgorithm {
/**
* sha256 with rsa
*/
SHA256_WITH_RSA,
/**
* sm2
*/
SM2;
}
/**
* 签名工具
*/
public static abstract class SignUtils {
/**
* 签名
*
* @param privateKey 私钥
* @param content 内容
* @return 签名串
*/
public static byte[] sha256WithRSASign(@NonNull String privateKey, byte[] content) throws Exception {
Assert.hasText(privateKey, "私钥不能为空");
if (content == null) {
return null;
}
PrivateKey privateKeyObj = toPrivateKey(privateKey, "RSA");
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKeyObj);
signature.update(content);
return signature.sign();
}
/**
* sm2签名
*
* @param privateKey 私钥
* @param content 内容
* @return 签名串
*/
public static byte[] sm2Sign(@NonNull String privateKey, byte[] content) throws Exception {
Assert.hasText(privateKey, "私钥不能为空");
if (content == null) {
return null;
}
ECPrivateKeyParameters priKeyParameters = toBCECPrivateKey(privateKey);
SM2Signer signer = new SM2Signer();
ParametersWithRandom pwr = new ParametersWithRandom(priKeyParameters, new SecureRandom());
signer.init(true, pwr);
signer.update(content, 0, content.length);
return signer.generateSignature();
}
/**
* 字符串转私钥对象
*
* @param privateKey 私钥字符串
* @return 私钥
*/
public static PrivateKey toPrivateKey(@NonNull String privateKey, @NonNull String algorithm) throws Exception {
if (!StringUtils.hasText(privateKey)) {
throw new IllegalArgumentException("私钥不能为空");
}
byte[] encodedKey = Base64.getDecoder().decode(privateKey.getBytes(StandardCharsets.UTF_8));
KeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePrivate(keySpec);
}
/**
* 字符串转私钥对象
*
* @param privateKey 私钥字符串
* @return 私钥
*/
public static ECPrivateKeyParameters toBCECPrivateKey(@NonNull String privateKey) throws Exception {
byte[] encodedKey = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance("EC",new BouncyCastleProvider());
BCECPrivateKey ecPriKey = (BCECPrivateKey) kf.generatePrivate(peks);
ECParameterSpec parameterSpec = ecPriKey.getParameters();
ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH());
return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters);
}
}
/**
* 构造器
*
* @param url 请求地址
* @param accessKey 接入标识
* @param privateKey 私钥
* @param isMock 是否mock请求
*/
public ServicePlatformInvoker(@NonNull String url, @NonNull String accessKey, @NonNull String privateKey, boolean isMock) {
this(url, accessKey, privateKey, SignAlgorithm.SHA256_WITH_RSA, isMock);
}
/**
* 构造器
*
* @param url 请求地址
* @param accessKey 接入标识
* @param privateKey 私钥
* @param isMock 是否mock请求
*/
public ServicePlatformInvoker(@NonNull String url, @NonNull String accessKey, @NonNull String privateKey, @NonNull SignAlgorithm signAlgorithm, boolean isMock) {
Assert.hasText(url, "请求地址不能为空");
Assert.hasText(accessKey, "接入标识不能为空");
Assert.hasText(privateKey, "私钥不能为空");
this.url = url;
this.accessKey = accessKey;
this.privateKey = privateKey;
this.signAlgorithm = signAlgorithm;
this.isMock = isMock;
}
/**
* 执行调用
*
* @param serviceSign 服务标识
* @param dateFormat 数据格式
* @param content 业务内容
* @param version 版本号
* @param headers 自定义请求头
* @return 响应内容
*/
public String invoke(@NonNull String serviceSign, @NonNull DateFormat dateFormat, String content, @NonNull String version, MultiValueMap<String, String> headers) {
// 请求流水号
String requestId = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 20);
// 时间戳
String timestamp = String.valueOf(System.currentTimeMillis());
String format = dateFormat.getValue();
// 封装数据
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.set("access_key", "DYZWFWZX");
params.add("biz_content", content);
params.add("format", "json");
if (this.isMock) {
params.add("mock", "");
}
params.add("request_id", "2be36a654da24cc8bb20");
// params.add("timestamp", timestamp);
params.add("timestamp", "1701049618303");
params.add("version", "1.0");
// 获取签名字符串
List<String> signSourceParams = new ArrayList<>();
params.forEach((key, values) -> {
if (values != null && values.size() > 0) {
Object value = values.get(0);
if (value != null) {
String valueStr = value.toString();
if (!valueStr.isEmpty()) {
signSourceParams.add(String.format("%s=%s", key, valueStr));
}
}
}
});
Collections.sort(signSourceParams);
String sign = null;
try {
String paramStr = String.join("&", signSourceParams);
System.out.println("paramStr==>"+paramStr);
byte[] paramStrBytes = paramStr.getBytes(StandardCharsets.UTF_8);
byte[] signBytes = null;
switch (this.signAlgorithm) {
case SHA256_WITH_RSA:
signBytes = SignUtils.sha256WithRSASign(privateKey, paramStrBytes);
break;
case SM2:
signBytes = SignUtils.sm2Sign(privateKey, paramStrBytes);
break;
}
sign = Base64.getEncoder().encodeToString(signBytes);
} catch (Exception e) {
throw new RuntimeException("服务集成平台签名时发生错误", e);
}
params.add("sign", sign);
System.out.println("sign=>"+sign);
System.out.println("MEUCIAKK6Z+5w4ePP2aqlK84TA99qgCR35c09WFwiFZYkWZ3AiEAqx7AZztcagRGkEv5bisqP+Wxq7fGinHzk+gkIJWF6oA=");
// 发送POST请求, 并获取响应
if (headers == null) {
headers = new HttpHeaders();
}
String responseContent;
try {
headers.set("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
ResponseEntity<String> responseEntity = restTemplate.exchange(url + serviceSign, HttpMethod.POST, new HttpEntity<>(params, headers), String.class);
responseContent = responseEntity.getBody();
} catch (Exception e) {
throw new RuntimeException("网络错误: " + e.getMessage());
}
JSONObject jsonObject = JSON.parseObject(responseContent);
String code = jsonObject.getString("code");
String msg = jsonObject.getString("msg");
String subCode = jsonObject.getString("sub_code");
String subMsg = jsonObject.getString("sub_msg");
if (!SUCCESS.equals(code)) {
throw new RuntimeException("服务集成平台调用错误:" + msg + "-" + subMsg);
}
return jsonObject.getString("biz_data");
}
/**
* 获取结果
*
* @param inputStream 输入流
* @return 响应体
*/
private static String getResult(InputStream inputStream) {
String result = "";
ByteArrayOutputStream dataOutputStream = null;
try {
byte[] buf = new byte[1024];
int n;
dataOutputStream = new ByteArrayOutputStream();
while (((n = inputStream.read(buf)) != -1)) {
dataOutputStream.write(buf, 0, n);
}
dataOutputStream.toByteArray();
result = new String(dataOutputStream.toByteArray(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
/**
* 执行调用
*
* @param serviceSign 服务标识
* @param dateFormat 数据格式
* @param content 业务内容
* @return 响应内容
*/
public String invoke(String serviceSign, DateFormat dateFormat, String content) {
return invoke(serviceSign, dateFormat, content, DEFAULT_VERSION, null);
}
/**
* 执行json参数调用
*
* @param serviceSign 服务标识
* @param params 参数
* @param headers 自定义请求头
* @return 响应内容
*/
public String invokeJSON(String serviceSign, Object params, MultiValueMap<String, String> headers) {
return invoke(serviceSign, DateFormat.JSON, JSON.toJSONString(params), DEFAULT_VERSION, headers);
}
/**
* 执行json参数调用
*
* @param serviceSign 服务标识
* @param params 参数
* @return 响应内容
*/
public String invokeJSON(String serviceSign, Object params) {
return invokeJSON(serviceSign, params, (MultiValueMap<String, String>) null);
}
/**
* 执行json参数调用
*
* @param serviceSign 服务标识
* @param params 参数
* @param version 版本号
* @return 响应内容
*/
public String invokeJSON(String serviceSign, Object params, String version) {
return invoke(serviceSign, DateFormat.JSON, JSON.toJSONString(params), version, null);
}
/**
* 执行json参数调用
*
* @param serviceSign 服务标识
* @param params 参数
* @param clazz 响应数据类型
* @param <T> 响应数据类型
* @return 响应内容
*/
public <T> T invokeJSON(String serviceSign, Object params, Class<T> clazz) {
return invokeJSON(serviceSign, params, clazz, DEFAULT_VERSION);
}
/**
* 执行json参数调用
*
* @param serviceSign 服务标识
* @param params 参数
* @param clazz 响应数据类型
* @param version 版本号
* @param <T> 响应数据类型
* @return 响应内容
*/
public <T> T invokeJSON(String serviceSign, Object params, Class<T> clazz, String version) {
String responseContent = invokeJSON(serviceSign, params, version);
return JSON.parseObject(responseContent, clazz);
}
public static void main(String[] args) throws Exception {
String priKey = "MIICSwIBADCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v////////////////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEjAgEBBIIBVTCCAVECAQEEIL0TuUlJwA2kCWlXlb+zSd/2Rpt4kf42vIJWq5VGH5NXoIHjMIHgAgEBMCwGByqGSM49AQECIQD////+/////////////////////wAAAAD//////////zBEBCD////+/////////////////////wAAAAD//////////AQgKOn6np2fXjRNWp5Lz2UJp/OXifUVq4+S3by9QU2UDpMEQQQyxK4sHxmBGV+ZBEZqOcmUj+MLv/JmC+FxWkWJM0x0x7w3NqL09necWb3O42tpIVPQqYd8xipHQALfMuUhOfCgAiEA/////v///////////////3ID32shxgUrU7v0CTnVQSMCAQGhRANCAATFqcMDO2aQJzPnu3LIm8uYBlNh8RwZfwEGBHiez2GFedbSDORLvkdagF0tLhlwXlU5KmM4fudIZoJVRNccY1pq";
String content = "{\"access_key\":\"DYZWFWZX\",\"biz_content\":\"{\\\"appid\\\":\\\"uRsNCSjIRWaN\\\",\\\"aaz001\\\":\\\"202311246\\\",\\\"key_set\\\":\\\"0cHyD1AaGPJZQlkNbOBDdYZDOJG9ZKgfQx+Cg402jLG9k2dvIHUyIhczyilsD8V5AgEsRxySmCbP8QcA+l7p1aeOSJxCWZt\\\\\\/GEQrRFCWEAv9HgHRMUmaVPPn8DHtfS2zZSH\\\\\\/aNERu4SIfyl19GJVygjWglDixUwyRNvW0U0ZM6HMFZEqWV005hRbhk4APeZ+PH9t1wU0A2nGZnvzdrX6RRMYKboqkHPYl18nczQB3cA=\\\"}\",\"format\":\"json\",\"request_id\":\"2023112454559857\",\"timestamp\":\"1700811926506\",\"version\":\"1.0\"}";
JSONObject jsonObject = JSON.parseObject(content);
String access_key = jsonObject.getString("access_key");
String biz_content = jsonObject.getString("biz_content");
String format = jsonObject.getString("format");
String request_id = jsonObject.getString("request_id");
String timestamp = jsonObject.getString("timestamp");
String version = jsonObject.getString("version");
StringBuilder signSb = new StringBuilder();
signSb.append("access_key").append("=").append(access_key).append("&");
signSb.append("biz_content").append("=").append(biz_content).append("&");
signSb.append("format").append("=").append(format).append("&");
signSb.append("request_id").append("=").append(request_id).append("&");
signSb.append("timestamp").append("=").append(timestamp).append("&");
signSb.append("version").append("=").append(version).append("&");
String text = signSb.substring(0, signSb.length() - 1);
byte[] signBytes = SignUtils.sm2Sign(priKey, text.getBytes());
System.out.println(Base64.getEncoder().encodeToString(signBytes));
}
}
...@@ -196,3 +196,27 @@ Content-Type: application/json ...@@ -196,3 +196,27 @@ Content-Type: application/json
###字典获取 ###字典获取
GET {{baseUrl}}/param/dict?first=SkinBase&second=imageResolution GET {{baseUrl}}/param/dict?first=SkinBase&second=imageResolution
###国密4加密
POST {{baseUrl}}/api/encrypt
Content-Type: application/json
{
"algorithm": "SM4",
"content": "ererfeiisgod",
"key": "QZTiVtyFIUjMCVLs",
"password": "QZTiVtyFIUjMCVLs",
"url": "https://cdsmk.cdrsigc.com/engine/rest/99999800009"
}
###国密4解密
POST {{baseUrl}}/api/decrypt
Content-Type: application/json
{
"algorithm": "SM4",
"content": "tbP0GEuSqSboA8qHissswQ==",
"key": "QZTiVtyFIUjMCVLs",
"password": "QZTiVtyFIUjMCVLs"
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment