/**
|
* Alipay.com Inc. Copyright (c) 2004-2019 All Rights Reserved.
|
*/
|
package com.alipay.easysdk.kernel.util;
|
|
import com.alipay.easysdk.kernel.AlipayConstants;
|
import org.bouncycastle.util.encoders.Base64;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import java.security.KeyFactory;
|
import java.security.PrivateKey;
|
import java.security.PublicKey;
|
import java.security.Signature;
|
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;
|
|
/**
|
* SHA256WithRSA签名器
|
*
|
* @author zhongyu
|
* @version $Id: Signer.java, v 0.1 2019年12月19日 9:10 PM zhongyu Exp $
|
*/
|
public class Signer {
|
private static final Logger LOGGER = LoggerFactory.getLogger(Signer.class);
|
|
public static String getSignCheckContent(Map<String, String> params) {
|
if (params == null) {
|
return null;
|
}
|
|
StringBuilder content = new StringBuilder();
|
List<String> keys = new ArrayList<>(params.keySet());
|
Collections.sort(keys);
|
for (int i = 0; i < keys.size(); i++) {
|
String key = keys.get(i);
|
String value = params.get(key);
|
content.append(i == 0 ? "" : "&").append(key).append("=").append(value);
|
}
|
return content.toString();
|
}
|
|
/**
|
* 验证签名
|
*
|
* @param content 待验签的内容
|
* @param sign 签名值的Base64串
|
* @param publicKeyPem 支付宝公钥
|
* @return true:验证成功;false:验证失败
|
*/
|
public static boolean verify(String content, String sign, String publicKeyPem) {
|
try {
|
KeyFactory keyFactory = KeyFactory.getInstance(AlipayConstants.RSA);
|
byte[] encodedKey = publicKeyPem.getBytes();
|
encodedKey = Base64.decode(encodedKey);
|
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
|
|
Signature signature = Signature.getInstance(AlipayConstants.SHA_256_WITH_RSA);
|
signature.initVerify(publicKey);
|
signature.update(content.getBytes(AlipayConstants.DEFAULT_CHARSET));
|
return signature.verify(Base64.decode(sign.getBytes()));
|
} catch (Exception e) {
|
String errorMessage = "验签遭遇异常,content=" + content + " sign=" + sign +
|
" publicKey=" + publicKeyPem + " reason=" + e.getMessage();
|
LOGGER.error(errorMessage, e);
|
throw new RuntimeException(errorMessage, e);
|
}
|
}
|
|
/**
|
* 计算签名
|
*
|
* @param content 待签名的内容
|
* @param privateKeyPem 私钥
|
* @return 签名值的Base64串
|
*/
|
public String sign(String content, String privateKeyPem) {
|
try {
|
byte[] encodedKey = privateKeyPem.getBytes();
|
encodedKey = Base64.decode(encodedKey);
|
PrivateKey privateKey = KeyFactory.getInstance(AlipayConstants.RSA).generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
|
|
Signature signature = Signature.getInstance(AlipayConstants.SHA_256_WITH_RSA);
|
signature.initSign(privateKey);
|
signature.update(content.getBytes(AlipayConstants.DEFAULT_CHARSET));
|
byte[] signed = signature.sign();
|
return new String(Base64.encode(signed));
|
} catch (Exception e) {
|
String errorMessage = "签名遭遇异常,content=" + content + " privateKeySize=" + privateKeyPem.length() + " reason=" + e.getMessage();
|
LOGGER.error(errorMessage, e);
|
throw new RuntimeException(errorMessage, e);
|
}
|
}
|
|
/**
|
* 对参数集合进行验签
|
*
|
* @param parameters 参数集合
|
* @param publicKey 支付宝公钥
|
* @return true:验证成功;false:验证失败
|
*/
|
public static boolean verifyParams(Map<String, String> parameters, String publicKey) {
|
String sign = parameters.get(AlipayConstants.SIGN_FIELD);
|
parameters.remove(AlipayConstants.SIGN_FIELD);
|
parameters.remove(AlipayConstants.SIGN_TYPE_FIELD);
|
|
String content = getSignCheckContent(parameters);
|
|
return verify(content, sign, publicKey);
|
}
|
}
|