Created by zdj on 2021/07/06.
*/
public class RSAUtil {
private static final Logger logger = LoggerFactory.getLogger(RSAUtil.class);
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static final String SIGN_CHARSET = “UTF-8”;
private static final String SIGN_TYPE_RSA = “RSA”;
private static final String SIGN_SHA256RSA_ALGORITHMS = “SHA256WithRSA”;
/市局参数/
// 测试环境 - 公钥
private static final String PUBLIC_KEY = “”;
// 正式环境 - 公钥,私钥
//private static final String PUBLIC_KEY = “”;
// private static final String PRIVATE_KEY = “”;
/本地参数/
//正式和测试都是这个
private static final String PRIVATE_KEY = “”;
// private static final String PUBLIC_KEY = “”;
/**
-
RSA2签名
-
@param map 待签名数据和签名字段字符串
-
@return 签名
-
@throws Exception 异常上层处理
*/
public static String rsaSign(Map<String, String> map) throws Exception {
// 将请求的参数封装处理下变成&符号连接的字符串
String content = getSignContent(map);
// 实例化私钥对象,然后根据参数字符串和私钥生成签名
PrivateKey priKey = getPrivateKeyFromPKCS8(new ByteArrayInputStream(PRIVATE_KEY.getBytes()));
Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(SIGN_CHARSET));
return new String(Base64.encodeBase64(signature.sign()));
}
/**
-
RSA2验签
-
@param map 待验签数据、签名信息和签名字段字符串
-
@return 验签结果 true/false
-
@throws Exception 异常上层处理
*/
public static boolean rsaCheck(Map<String, String> map) throws Exception {
// 将请求的参数封装处理下变成&符号连接的字符串
String content = getSignContent(map);
// 实例化公钥对象
PublicKey pubKey = getPublicKeyFromX509(new ByteArrayInputStream(PUBLIC_KEY.getBytes()));
Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
signature.initVerify(pubKey);
signature.update(content.getBytes(SIGN_CHARSET));
// 处理并返回验签结果
String sign = map.get(“sign”);
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
/**
- 把参数按照ASCII码递增排序,如果遇到相同字符则按照第二个字符的键值ASCII码递增排序
- 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来
- @param sortedParams 待签名数据和签名字段字符串
- @return 待签名字符串
*/
private static String getSignContent(Map<String, String> sortedParams) {
//appId,method,bizContent,生成签名所需的参数
String[] sign_param = sortedParams.get(“sign_param”).split(",");
List keys = new ArrayList<>();
Collections.addAll(keys, sign_param);
Collections.sort(keys);
StringBuilder content = new StringBuilder();
int index = 0;
for (String key : keys) {
String value = sortedParams.get(key);
if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) {
content.append(index == 0 ? “” : “&”).append(key).append("=").append(value);
index++;
}
}
return content.toString();
}
private static PrivateKey getPrivateKeyFromPKCS8(InputStream ins) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
byte[] encodedKey = readText(ins).getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
private static PublicKey getPublicKeyFromX509(InputStream ins) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
StringWriter writer = new StringWriter();
io(new InputStreamReader(ins), writer, -1);
byte[] encodedKey = writer.toString().getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
private static String readText(InputStream ins) throws IOException {
Reader reader = new InputStreamReader(ins);
StringWriter writer = new StringWriter();
io(reader, writer, -1);
return writer.toString();
}
private static void io(Reader in, Writer out, int bufferSize) throws IOException {
if (bufferSize == -1) {
bufferSize = DEFAULT_BUFFER_SIZE >> 1;
}
char[] buffer = new char[bufferSize];
int amount;
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
}
}