| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package com.dk.mdm.infrastructure.util;
- import org.springframework.stereotype.Component;
- import java.security.*;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
- import java.util.Base64;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Objects;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- /**
- * 签名工具类
- */
- @Component
- public class SignatureUtils {
- /**
- * 签名
- */
- public static final String HEADER_PARAM_API_VERIFY_SIGN = "apiVerifySign";
- /**
- * 随机字符串
- */
- public static final String HEADER_PARAM_API_VERIFY_NONCE = "apiVerifyNonce";
- /**
- * 时间戳
- */
- public static final String HEADER_PARAM_API_VERIFY_TS = "apiVerifyTS";
- /**
- * 应用标识
- */
- public static final String HEADER_PARAM_ACCESS_KEY = "accessKey";
- /**
- * 签名算法
- */
- private static final String RSA = "RSA";
- /**
- * 加密算法
- */
- private static final String SHA512_WITH_RSA = "SHA512withRSA";
- private SignatureUtils() {
- }
- /**
- * 执行签名
- *
- * @param rsaPrivateKey 私钥
- * @param toSignStr 参数内容
- * @return 签名后的内容,base64后的字符串
- */
- public static String executeSignature(String rsaPrivateKey, String toSignStr) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
- // base64解码私钥
- byte[] decodePrivateKey = Base64.getDecoder().decode(rsaPrivateKey.replace("\r\n", ""));
- PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decodePrivateKey);
- KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
- Signature signature = Signature.getInstance(SHA512_WITH_RSA);
- signature.initSign(privateKey);
- signature.update(toSignStr.getBytes());
- // 生成签名
- byte[] result = signature.sign();
- // base64编码签名为字符串
- return Base64.getEncoder().encodeToString(result);
- }
- /**
- * 验证签名
- *
- * @param rsaPublicKey 公钥
- * @param sign 签名
- * @param src 参数内容
- * @return 验证结果
- */
- public static boolean verifySignature(String rsaPublicKey, String sign, String src) throws IllegalArgumentException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
- // base64解码公钥
- byte[] decodePublicKey = Base64.getDecoder().decode(rsaPublicKey.replace("\r\n", ""));
- X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodePublicKey);
- KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
- Signature signature = Signature.getInstance(SHA512_WITH_RSA);
- signature.initVerify(publicKey);
- signature.update(src.getBytes());
- // base64解码签名为字节数组
- byte[] decodeSign = Base64.getDecoder().decode(sign);
- // 验证签名
- return signature.verify(decodeSign);
- }
- /**
- * 构建加签参数字符串
- *
- * @param urlParamsStr url参数(格式如:”a=1&b=2“)
- * @param bodyStr body参数
- * @param accessKey 应用标识
- * @param apiVerifyTS 时间戳
- * @param apiVerifyNonce 随机字符串
- * @return 签名字符串
- */
- public static String buildToSignatureStr(String urlParamsStr, String bodyStr, String accessKey, long apiVerifyTS, String apiVerifyNonce) {
- Map<String, Object> urlParams = null;
- if (null != urlParamsStr && !urlParamsStr.isEmpty()) {
- // 将url参数解析为Map
- urlParams = Stream.of(urlParamsStr.split("&"))
- .filter(Objects::nonNull)
- .map(String::trim)
- .filter(param -> !param.isEmpty())
- .map(param -> param.split("="))
- .filter(paramSplitArr -> paramSplitArr.length >= 2)
- .collect(Collectors.toMap(paramSplitArr -> paramSplitArr[0].trim(), paramSplitArr -> paramSplitArr[1].trim()));
- }
- return buildToSignatureStr(urlParams, bodyStr, accessKey, apiVerifyTS, apiVerifyNonce);
- }
- /**
- * 构建加签参数字符串
- *
- * @param urlParams url参数
- * @param bodyStr body参数
- * @param accessKey 应用标识
- * @param apiVerifyTS 时间戳
- * @param apiVerifyNonce 随机字符串
- * @return 签名字符串
- */
- public static String buildToSignatureStr(Map<String, Object> urlParams, String bodyStr, String accessKey, long apiVerifyTS, String apiVerifyNonce) {
- Map<String, Object> parameterMap = new HashMap<>();
- // 拼接时间戳与随机字符串
- parameterMap.put(HEADER_PARAM_ACCESS_KEY, accessKey);
- parameterMap.put(HEADER_PARAM_API_VERIFY_TS, apiVerifyTS);
- parameterMap.put(HEADER_PARAM_API_VERIFY_NONCE, apiVerifyNonce);
- // 拼接请求参数
- if (urlParams != null && !urlParams.isEmpty()) {
- parameterMap.putAll(urlParams);
- }
- StringBuilder sb = new StringBuilder();
- // 字典序排序拼接
- parameterMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry ->
- sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&")
- );
- String substring = sb.substring(0, sb.length() - 1);
- return null == bodyStr || bodyStr.isEmpty() ? substring : substring + ";" + bodyStr;
- }
- }
|