package com.nova.sankuai.domain.api.zhongan; import java.io.ByteArrayOutputStream; import java.security.Key; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Function; import javax.crypto.Cipher; import org.apache.commons.lang.StringUtils; import org.apache.tomcat.util.codec.binary.Base64; import lombok.AllArgsConstructor; import lombok.Getter; /** *

* description *

* * @author denglb 2021/11/15 */ public class SignUtil { public static final String CHARSET = "UTF-8"; public static final String RSA_ALGORITHM = "RSA"; public static final String RSA_ALGORITHM_SIGN_SHA1 = "SHA1WithRSA"; public static final String RSA_ALGORITHM_SIGN_SHA256 = "SHA256withRSA"; public static String doSign(Map map, String privateKeyStr) { try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过X509编码的Key指令获得公钥对象 // X509EncodedKeySpec x509KeySpec = new // X509EncodedKeySpec(Base64.decodeBase64(publicKey)); // this.publicKey = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); // 通过PKCS#8编码的Key指令获得私钥对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); String data = getSignContent(map); Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN_SHA256); signature.initSign(privateKey); signature.update(data.getBytes(CHARSET)); return Base64.encodeBase64String(signature.sign()); } catch (Exception e) { throw new RuntimeException("签名失败", e); } } public static String doSignWithNoOrder(String content, String privateKeyStr) { try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过X509编码的Key指令获得公钥对象 // X509EncodedKeySpec x509KeySpec = new // X509EncodedKeySpec(Base64.decodeBase64(publicKey)); // this.publicKey = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); // 通过PKCS#8编码的Key指令获得私钥对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec( Base64.decodeBase64(privateKeyStr)); RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN_SHA256); signature.initSign(privateKey); signature.update(content.getBytes()); return Base64.encodeBase64String(signature.sign()); } catch (Exception e) { throw new RuntimeException("签名失败", e); } } /** * 参数格式转换Map转String * * @param sortedParams * @return */ public static String getSignContent(Map sortedParams) { StringBuffer content = new StringBuffer(); List keys = new ArrayList<>(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (String key : keys) { String value = sortedParams.get(key).toString(); if (isNotEmpty(key) && isNotEmpty(value)) { content.append((index == 0 ? "" : "&") + key + "=" + value); index++; } } return content.toString(); } private static boolean isNotEmpty(String str) { return ((str != null) && (str.length() > 0)); } private static boolean isEmpty(String str) { return ((str == null) || (str.length() == 0)); } /** * 私钥加密 * * @return String 加密数据 */ public static String encryptByPrivateKey(Map map, String privateKeyStr) throws Exception { try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过PKCS#8编码的Key指令获得私钥对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); // 数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 待加密内容 String content = getSignContent(map); byte[] data = cipher.doFinal(content.getBytes(CHARSET)); return Base64.encodeBase64String(data); } catch (Exception e) { throw new RuntimeException("私钥加密失败", e); } } /** * 公钥加密 * * @return String 加密数据 */ public static String encryptByPublicKey(Map map, String publicKeyStr) { try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过X509编码的Key指令获得公钥对象 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr)); RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); // 数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 待加密内容 String content = getSignContent(map); byte[] data = cipher.doFinal(content.getBytes(CHARSET)); return Base64.encodeBase64String(data); } catch (Exception e) { throw new RuntimeException("公钥加密失败", e); } } /** * 公钥加密(无排序) * * @return String 加密数据 */ public static String encryptByPublicKeyWithNoOrderForLongData(String content, String publicKeyStr) { try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过X509编码的Key指令获得公钥对象 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec( Base64.decodeBase64(publicKeyStr)); RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); // 数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] data = content.getBytes(); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; while (inputLen - offSet > 0) { if (inputLen - offSet > 117) { cache = cipher.doFinal(data, offSet, 117); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 117; } byte[] encryptedData = out.toByteArray(); out.close(); return Base64.encodeBase64String(encryptedData); } catch (Exception e) { throw new RuntimeException("公钥加密失败", e); } } /** * RSA-私钥解密过程 * * @param context * @param privateKeyStr * @return * @throws Exception */ public static String decryptRSA(String context, String privateKeyStr) { if (isEmpty(privateKeyStr)) { throw new RuntimeException("解密私钥为空, 请设置"); } Cipher cipher; try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过PKCS#8编码的Key指令获得私钥对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); // 使用默认RSA cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] output = cipher.doFinal(Base64.decodeBase64(context)); return new String(output); } catch (Exception e) { throw new RuntimeException("解密数据失败"); } } /** * RSA-私钥解密过程(长度超128byte分段解密) * * @param context * @param privateKeyStr * @return * @throws Exception */ public static String decryptRSAByPrivateKeyForLongData(String context, String privateKeyStr) { if (isEmpty(privateKeyStr)) { throw new RuntimeException("解密私钥为空, 请设置"); } Cipher cipher; try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 通过PKCS#8编码的Key指令获得私钥对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); // 使用默认RSA cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] encryptedData = Base64.decodeBase64(context); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > 128) { cache = cipher.doFinal(encryptedData, offSet, 128); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 128; } out.close(); return out.toString(); } catch (Exception e) { throw new RuntimeException("解密数据失败"); } } /** * 根据加签类型验证签名 * * @param signParams * @param sign * @param publicKey * @return */ public static boolean rsa256CheckContent(Map signParams, String sign, String publicKey) { try { String content = getSignContent(signParams); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decodeBase64(publicKey); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); java.security.Signature signature = java.security.Signature.getInstance(RSA_ALGORITHM_SIGN_SHA256); signature.initVerify(pubKey); signature.update(content.getBytes(CHARSET)); boolean bverify = signature.verify(Base64.decodeBase64(sign)); return bverify; } catch (Exception e) { throw new RuntimeException("验签失败"); } } /** * 根据加签类型验证签名 * * @param sign * @param publicKey * @return */ public static boolean rsa256CheckContentWithNoOrder(String content, String sign, String publicKey) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decodeBase64(publicKey); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN_SHA256); signature.initVerify(pubKey); signature.update(content.getBytes(CHARSET)); boolean bverify = signature.verify(Base64.decodeBase64(sign)); return bverify; } catch (Exception e) { throw new RuntimeException("验签失败"); } } /** * RSA签名 * * @param content 待签名的字符串 * @param privateKey rsa私钥字符串 * @return */ public static String doRsaSign(String content, String privateKey) { return doRsaSign(content, privateKey, CHARSET); } /** * RSA签名 * * @param content 待签名的字符串 * @param privateKey rsa私钥字符串 * @param charset 字符编码 * @return */ public static String doRsaSign(String content, String privateKey, String charset) { try { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyf.generatePrivate(priPKCS8); Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN_SHA1); signature.initSign(priKey); if (StringUtils.isEmpty(charset)) { signature.update(content.getBytes()); } else { signature.update(content.getBytes(charset)); } byte[] signed = signature.sign(); return new String(Base64.encodeBase64(signed)); } catch (Exception e) { throw new RuntimeException("签名失败", e); } } /** * @param content 待签名数据 * @param sign 签名值 * @param publicKey 分配给开发商公钥 * @return */ public static boolean doRsaSignCheck(String content, String sign, String publicKey) { return doRsaSignCheck(content, sign, publicKey, CHARSET); } /** * RSA验签 * * @param content 待签名数据 * @param sign 签名值 * @param publicKey 分配给开发商公钥 * @param charset 字符集编码 * @return */ public static boolean doRsaSignCheck(String content, String sign, String publicKey, String charset) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decodeBase64(publicKey); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN_SHA1); signature.initVerify(pubKey); signature.update(content.getBytes(charset)); return signature.verify(Base64.decodeBase64(sign)); } catch (Exception e) { throw new RuntimeException("验签失败", e); } } public static String encryptRSAByPrivateKey(String content, String privateKey) { return doRSA(content, privateKey, KeyTypeEnum.PRIVATE_KEY, RSATypeEnum.ENCRYPT_MODE); } public static String encryptRSAByPublicKey(String content, String publicKey) { return doRSA(content, publicKey, KeyTypeEnum.PUBLIC_KEY, RSATypeEnum.ENCRYPT_MODE); } public static String decryptRSAByPrivateKey(String content, String privateKey) { return doRSA(content, privateKey, KeyTypeEnum.PRIVATE_KEY, RSATypeEnum.DECRYPT_MODE); } public static String decryptRSAByPublicKey(String content, String publicKey) { return doRSA(content, publicKey, KeyTypeEnum.PUBLIC_KEY, RSATypeEnum.DECRYPT_MODE); } private static String doRSA(String content, String key, KeyTypeEnum keyType, RSATypeEnum rsaType) { if (StringUtils.isEmpty(key)) { throw new RuntimeException(keyType.getDesc() + "为空, 请设置"); } try { KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); // 数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(rsaType.getCipherMode(), keyType.getKeyFunction().apply(keyFactory, key)); return rsaType.returnFunction.apply(cipher, content); } catch (Exception e) { throw new RuntimeException(rsaType.getErrMsg(), e); } } @FunctionalInterface public interface MyBiFunction { R apply(T t, U u) throws Exception; default MyBiFunction andThen(Function after) throws Exception { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); } } @Getter @AllArgsConstructor public enum KeyTypeEnum { PRIVATE_KEY(0, "私钥", (keyFactory, key) -> keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(key)))), PUBLIC_KEY(1, "公钥", (keyFactory, key) -> keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(key)))), ; private Integer code; private String desc; private MyBiFunction keyFunction; } @Getter @AllArgsConstructor public enum RSATypeEnum { DECRYPT_MODE(0, "解密模式", Cipher.DECRYPT_MODE, "RSA解密失败", (cipher, txt) -> new String(cipher.doFinal(Base64.decodeBase64(txt)))), ENCRYPT_MODE(1, "加密模式", Cipher.ENCRYPT_MODE, "RSA加密失败", (cipher, txt) -> Base64.encodeBase64String(cipher.doFinal(txt.getBytes(CHARSET)))), ; private Integer code; private String desc; private int cipherMode; private String errMsg; private MyBiFunction returnFunction; } }