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 super R, ? extends V> 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;
}
}