/**
|
*
|
* Licensed Property to China UnionPay Co., Ltd.
|
*
|
* (C) Copyright of China UnionPay Co., Ltd. 2010
|
* All Rights Reserved.
|
*
|
*
|
* Modification History:
|
* =============================================================================
|
* Author Date Description
|
* ------------ ---------- ---------------------------------------------------
|
* xshu 2014-05-28 证书工具类.
|
* =============================================================================
|
*/
|
package com.stylefeng.guns.modular.account.util;
|
|
|
import com.stylefeng.guns.core.log.LogManager;
|
|
import java.io.*;
|
import java.math.BigInteger;
|
import java.security.KeyFactory;
|
import java.security.KeyStore;
|
import java.security.PrivateKey;
|
import java.security.Provider;
|
import java.security.PublicKey;
|
import java.security.Security;
|
import java.security.cert.CertPathBuilder;
|
import java.security.cert.CertStore;
|
import java.security.cert.CertificateFactory;
|
import java.security.cert.CollectionCertStoreParameters;
|
import java.security.cert.PKIXBuilderParameters;
|
import java.security.cert.PKIXCertPathBuilderResult;
|
import java.security.cert.TrustAnchor;
|
import java.security.cert.X509CertSelector;
|
import java.security.cert.X509Certificate;
|
import java.security.spec.RSAPublicKeySpec;
|
import java.util.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import org.apache.commons.io.FileUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import static com.stylefeng.guns.modular.account.util.SDKConstants.POINT;
|
import static com.stylefeng.guns.modular.account.util.SDKConstants.UNIONPAY_CNNAME;
|
import static com.stylefeng.guns.modular.account.util.SDKUtil.isEmpty;
|
|
/**
|
* @ClassName: CertUtil
|
* @Description: acpsdk证书工具类,主要用于对证书的加载和使用
|
* @date 2016-7-22 下午2:46:20
|
* 声明:以下代码只是为了方便接入方测试而提供的样例代码,商户可以根据自己需要,按照技术文档编写。该代码仅供参考,不提供编码,性能,规范性等方面的保障
|
*/
|
public class CertUtil {
|
|
private static Logger logger = LoggerFactory.getLogger(LogManager.class);
|
|
/** 验签中级证书 */
|
private static X509Certificate middleCert = null;
|
/** 验签根证书 */
|
private static X509Certificate rootCert = null;
|
/** 5.0磁道加密公钥 */
|
private static PublicKey encryptTrackKey = null;
|
/** 签名私钥map:证书路径,私钥 */
|
private final static Map<String, Cert> signCerts = new ConcurrentHashMap<String, Cert>();
|
/** 5.0接口验签证书Map:certId,公钥 */
|
private static Map<String, PublicKey> verifyCerts = new ConcurrentHashMap<String, PublicKey>();
|
/** 加密证书 */
|
private static Cert encryptCert = null;
|
/** 5.1接口验签证书Map:证书完整字符串,公钥 */
|
private static Map<String, PublicKey> verifyCerts510 = new ConcurrentHashMap<String, PublicKey>();
|
/** 6.0统一支付加密pin用,其他接口请勿使用 */
|
private static Cert pinEncryptCert = null;
|
|
protected static class Cert {
|
protected String certId;
|
protected PublicKey pubKey;
|
protected PrivateKey priKey;
|
}
|
|
static {
|
addProvider();//向系统添加BC provider
|
init();
|
}
|
|
/**
|
* 初始化所有证书.
|
*/
|
public static void init() {
|
try {
|
initSignCert();//初始化签名私钥证书
|
initMiddleCert();//初始化验签证书的中级证书
|
initRootCert();//初始化验签证书的根证书
|
initEncryptCert();//初始化加密公钥
|
initPinEncryptCert();//初始化pin加密公钥
|
initTrackKey();//构建磁道加密公钥
|
initValidateCertFromDir();//初始化所有的验签证书
|
} catch (Exception e) {
|
logger.error("init失败。", e);
|
}
|
}
|
|
/**
|
* 添加签名,验签,加密算法提供者
|
*/
|
private static void addProvider(){
|
if (Security.getProvider("BC") == null) {
|
logger.debug("add BC provider");
|
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
} else {
|
Security.removeProvider("BC"); //解决eclipse调试时tomcat自动重新加载时,BC存在不明原因异常的问题。
|
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
logger.debug("re-add BC provider");
|
}
|
printSysInfo();
|
}
|
|
/**
|
*
|
* @param path
|
* @param pwd
|
* @return
|
*/
|
private static Cert addSignCert(String path, String pwd) {
|
|
if (isEmpty(path) || isEmpty(pwd)) {
|
logger.warn("签名证书路径或证书密码为空。 停止加载签名私钥证书。");
|
return null;
|
}
|
|
final String type = "PKCS12"; //实际BC只支持PKCS12,不支持JKS,就不去管JKS了……
|
|
logger.info("加载签名私钥证书==>" + path);
|
FileInputStream fis = null;
|
try {
|
KeyStore ks = KeyStore.getInstance(type, "BC");
|
logger.debug("Load RSA CertPath=[" + path + "],Pwd=["+ pwd + "]");
|
fis = new FileInputStream(path);
|
char[] nPassword = null;
|
nPassword = null == pwd || "".equals(pwd.trim()) ? null: pwd.toCharArray();
|
if (null != ks) {
|
ks.load(fis, nPassword);
|
}
|
Enumeration<String> aliasenum = null;
|
aliasenum = ks.aliases();
|
String keyAlias = null;
|
if (aliasenum.hasMoreElements()) {
|
keyAlias = aliasenum.nextElement();
|
}
|
X509Certificate cert = (X509Certificate) ks.getCertificate(keyAlias);
|
|
Cert c = new Cert();
|
c.certId = cert.getSerialNumber().toString(10);
|
c.priKey = (PrivateKey) ks.getKey(keyAlias, pwd.toCharArray());
|
c.pubKey = cert.getPublicKey();
|
signCerts.put(path, c);
|
logger.info("addSignCert Successful. CertId=[" + c.certId + "]");
|
return c;
|
} catch (Exception e) {
|
logger.error("addSignCert Error", e);
|
} finally {
|
if(null!=fis)
|
try {
|
fis.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
return null;
|
}
|
|
|
/**
|
* 指定路径读个x509证书
|
* @param path
|
* @return
|
*/
|
public static X509Certificate readX509Cert(String path) {
|
X509Certificate cert = null;
|
CertificateFactory cf = null;
|
FileInputStream in = null;
|
try {
|
cf = CertificateFactory.getInstance("X.509", "BC");
|
in = new FileInputStream(path);
|
cert = (X509Certificate) cf.generateCertificate(in);
|
} catch (FileNotFoundException e) {
|
logger.error("readX509Cert Error File Not Found: " + path, e);
|
} catch (Exception e) {
|
logger.error("readX509Cert Error", e);
|
} finally {
|
if (null != in) {
|
try {
|
in.close();
|
} catch (IOException e) {
|
}
|
}
|
}
|
return cert;
|
}
|
/**
|
* 用配置文件acp_sdk.properties中配置的私钥路径和密码 加载签名证书,会清空重新加载,一般仅第一次加载时调用即可
|
*/
|
private static void initSignCert() {
|
signCerts.clear();
|
String path = SDKConfig.getConfig().getSignCertPath();
|
String pwd = SDKConfig.getConfig().getSignCertPwd();
|
if(isEmpty(path) || isEmpty(pwd)) {
|
logger.warn(SDKConfig.SDK_SIGNCERT_PATH + " or " + SDKConfig.SDK_SIGNCERT_PWD + " is empty");
|
return;
|
}
|
Cert cert = addSignCert(path, pwd);
|
logger.info("读取配置文件默认签名证书==>" + path + (cert != null ?"成功":"失败"));
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载5.1验签证书中级证书
|
*/
|
private static void initMiddleCert() {
|
String path = SDKConfig.getConfig().getMiddleCertPath();
|
if(isEmpty(path)){
|
logger.warn(SDKConfig.SDK_MIDDLECERT_PATH + " is empty");
|
return;
|
}
|
middleCert = readX509Cert(path);
|
logger.info("加载中级证书==>" + path + (middleCert != null ?"成功":"失败"));
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载5.1验签证书根证书
|
*/
|
private static void initRootCert() {
|
String path = SDKConfig.getConfig().getRootCertPath();
|
if(isEmpty(path)){
|
logger.warn(SDKConfig.SDK_ROOTCERT_PATH + " is empty");
|
return;
|
}
|
rootCert = readX509Cert(path);
|
logger.info("加载根证书==>" + path + (rootCert != null ?"成功":"失败"));
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载磁道公钥
|
*/
|
private static void initTrackKey() {
|
|
String modulus = SDKConfig.getConfig().getEncryptTrackKeyModulus();
|
String exponent = SDKConfig.getConfig().getEncryptTrackKeyExponent();
|
if(isEmpty(modulus) || isEmpty(exponent)){
|
logger.warn(SDKConfig.SDK_ENCRYPTTRACKKEY_MODULUS + " or " + SDKConfig.SDK_ENCRYPTTRACKKEY_EXPONENT + " is empty");
|
return;
|
}
|
encryptTrackKey = getPublicKey(modulus, exponent);
|
logger.info("加载5.0磁道公钥==>" + (encryptTrackKey != null ?"成功":"失败"));
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载验签证书
|
*/
|
private static void initValidateCertFromDir() {
|
|
verifyCerts.clear();
|
|
String dir = SDKConfig.getConfig().getValidateCertDir();
|
if (isEmpty(dir)) {
|
logger.error("WARN: acpsdk.validateCert.dir is empty");
|
return;
|
}
|
|
logger.info("加载验证签名证书目录==>" + dir +" 注:如果请求报文中version=5.1.0那么此验签证书目录使用不到,可以不需要设置(version=5.0.0必须设置)。");
|
File fileDir = new File(dir);
|
File[] files = fileDir.listFiles(new CerFilter());
|
for (int i = 0; i < files.length; i++) {
|
File file = files[i];
|
try {
|
X509Certificate verifyCert = readX509Cert(file.getAbsolutePath());
|
if(verifyCert == null) {
|
continue;
|
}
|
String certId = verifyCert.getSerialNumber().toString(10);
|
verifyCerts.put(certId, verifyCert.getPublicKey());
|
logger.info("[" + file.getAbsolutePath() + "][CertId=" + certId + "]");
|
} catch (Exception e) {
|
logger.error("Load verify cert error, " + file.getAbsolutePath(), e);
|
}
|
}
|
logger.info("LoadVerifyCert Finish");
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书
|
*/
|
private static void initEncryptCert() {
|
String path = SDKConfig.getConfig().getEncryptCertPath();
|
if(isEmpty(path)){
|
logger.warn(SDKConfig.SDK_ENCRYPTCERT_PATH + " is empty");
|
return;
|
}
|
X509Certificate encryptCert = readX509Cert(path);
|
logger.info("加载敏感信息加密证书==>" + path + (encryptCert != null ?"成功":"失败"));
|
if(encryptCert != null) {
|
Cert c = new Cert();
|
c.certId = encryptCert.getSerialNumber().toString(10);
|
c.pubKey = encryptCert.getPublicKey();
|
CertUtil.encryptCert = c;
|
}
|
}
|
|
/**
|
* 用配置文件acp_sdk.properties配置路径 加载6.0统一支付产品pin加密证书
|
*/
|
private static void initPinEncryptCert() {
|
String path = SDKConfig.getConfig().getPinEncryptCertPath();
|
if(isEmpty(path)){
|
logger.warn(SDKConfig.SDK_PINENCRYPTCERT_PATH + " is empty");
|
return;
|
}
|
X509Certificate encryptCert = readX509Cert(path);
|
logger.info("加载6.0统一支付产品pin加密证书==>" + path + (encryptCert != null ?"成功":"失败"));
|
if(encryptCert != null) {
|
Cert c = new Cert();
|
c.certId = encryptCert.getSerialNumber().toString(10);
|
c.pubKey = encryptCert.getPublicKey();
|
CertUtil.pinEncryptCert = c;
|
}
|
}
|
|
/**
|
*
|
*/
|
private static Cert getSignCert() {
|
String path = SDKConfig.getConfig().getSignCertPath();
|
String pwd = SDKConfig.getConfig().getSignCertPwd();
|
if(isEmpty(path) || isEmpty(pwd)) {
|
logger.error("未配置默认签名证书时无法调用此方法。");
|
return null;
|
}
|
return getSignCert(path, pwd);
|
}
|
|
/**
|
*
|
* @param path
|
* @param pwd
|
* @return
|
*/
|
private static Cert getSignCert(String path, String pwd) {
|
if(isEmpty(path) || isEmpty(pwd)) {
|
logger.error("传入的签名路径或密码为空。");
|
return null;
|
}
|
if(!signCerts.containsKey(path)){
|
addSignCert(path, pwd);
|
}
|
Cert c = signCerts.get(path);
|
if(c == null) {
|
logger.error("未成功获取签名证书。");
|
return null;
|
}
|
return c;
|
}
|
|
/**
|
* 获取敏感信息加密证书PublicKey
|
*
|
* @return
|
*/
|
protected static Cert getEncryptCert() {
|
if(CertUtil.encryptCert == null) {
|
initEncryptCert();
|
}
|
return CertUtil.encryptCert;
|
}
|
|
/**
|
* 获取敏感信息加密证书PublicKey
|
*
|
* @return
|
*/
|
protected static Cert getPinEncryptCert() {
|
if(CertUtil.pinEncryptCert == null) {
|
initPinEncryptCert();
|
}
|
return CertUtil.pinEncryptCert;
|
}
|
|
/**
|
* 重置敏感信息加密证书公钥。
|
*/
|
public static int resetEncryptCertPublicKey(String strCert) {
|
if (isEmpty(strCert)) {
|
logger.error("传入证书信息为空。");
|
return -1;
|
}
|
|
X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert);
|
// 没换,不需要更新
|
if (CertUtil.getEncryptCert().certId.equals(
|
x509Cert.getSerialNumber().toString(10))) {
|
logger.info("返回证书和原证书一样,不用更新。");
|
return 0;
|
}
|
|
final String localCertPath = SDKConfig.getConfig().getEncryptCertPath();
|
if(isEmpty(localCertPath)){
|
logger.error("未配置加密证书路径,无法执行此方法。");
|
return -1;
|
}
|
File f = new File(localCertPath);
|
if(!f.exists()) {
|
logger.warn("原加密证书不存在:" + localCertPath);
|
} else {
|
// 将本地证书进行备份存储
|
int i = localCertPath.lastIndexOf(POINT);
|
String leftFileName = localCertPath.substring(0, i);
|
String rightFileName = localCertPath.substring(i + 1);
|
String newFileName = leftFileName + "_backup" + POINT + rightFileName;
|
try {
|
FileUtils.copyFile(f, new File(newFileName));
|
logger.info("原加密证书备份成功。");
|
} catch (IOException e) {
|
logger.error("原加密证书备份失败,停止改证书。", e);
|
return -1;
|
}
|
}
|
// 备份成功,进行新证书的存储
|
try {
|
FileUtils.writeByteArrayToFile(f, strCert.getBytes(), false);
|
logger.info("加密证书更新成功。");
|
initEncryptCert();
|
return 1;
|
} catch (IOException e) {
|
logger.error("加密证书更新失败。", e);
|
return -1;
|
}
|
}
|
|
/**
|
* 重置pin敏感信息加密证书公钥。
|
*/
|
public static int resetPinEncryptCertPublicKey(String strCert) {
|
if (isEmpty(strCert)) {
|
logger.error("传入证书信息为空。");
|
return -1;
|
}
|
|
X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert);
|
// 没换,不需要更新
|
if (CertUtil.getPinEncryptCert().certId.equals(
|
x509Cert.getSerialNumber().toString(10))) {
|
logger.info("返回证书和原证书一样,不用更新。");
|
return 0;
|
}
|
|
final String localCertPath = SDKConfig.getConfig().getPinEncryptCertPath();
|
if(isEmpty(localCertPath)){
|
logger.error("未配置加密证书路径,无法执行此方法。");
|
return -1;
|
}
|
File f = new File(localCertPath);
|
if(!f.exists()) {
|
logger.warn("原加密证书不存在:" + localCertPath);
|
} else {
|
// 将本地证书进行备份存储
|
int i = localCertPath.lastIndexOf(POINT);
|
String leftFileName = localCertPath.substring(0, i);
|
String rightFileName = localCertPath.substring(i + 1);
|
String newFileName = leftFileName + "_backup" + POINT + rightFileName;
|
try {
|
FileUtils.copyFile(f, new File(newFileName));
|
logger.info("原加密证书备份成功。");
|
} catch (IOException e) {
|
logger.error("原加密证书备份失败,停止改证书。", e);
|
return -1;
|
}
|
}
|
// 备份成功,进行新证书的存储
|
try {
|
FileUtils.writeByteArrayToFile(f, strCert.getBytes(), false);
|
logger.info("加密证书更新成功。");
|
initPinEncryptCert();
|
return 1;
|
} catch (IOException e) {
|
logger.error("加密证书更新失败。", e);
|
return -1;
|
}
|
}
|
|
/**
|
* 获取磁道加密证书PublicKey
|
*
|
* @return
|
*/
|
public static PublicKey getEncryptTrackPublicKey() {
|
if (null == encryptTrackKey) {
|
initTrackKey();
|
}
|
return encryptTrackKey;
|
}
|
|
/**
|
* 通过certId获取验签证书Map中对应证书PublicKey
|
*
|
* @param certId 证书物理序号
|
* @return 通过证书编号获取到的公钥
|
*/
|
public static PublicKey getValidatePublicKey(String certId) {
|
if(certId == null) {
|
logger.error("没有传入certId.");
|
return null;
|
}
|
if (!verifyCerts.containsKey(certId)) {
|
initValidateCertFromDir();
|
}
|
PublicKey result = verifyCerts.get(certId);
|
if(result == null) {
|
logger.error("缺少certId=[" + certId + "]对应的验签证书.");
|
return null;
|
}
|
return result;
|
}
|
|
/**
|
* 获取配置文件acp_sdk.properties中配置的签名私钥证书certId
|
*
|
* @return 证书的物理编号
|
*/
|
public static String getSignCertId() {
|
Cert c = getSignCert();
|
if(c == null) return null;
|
return c.certId;
|
}
|
|
/**
|
* 获取配置文件acp_sdk.properties中配置的签名私钥证书私钥
|
*
|
* @return 证书的物理编号
|
*/
|
public static PrivateKey getSignCertPrivateKey() {
|
Cert c = getSignCert();
|
if(c == null) return null;
|
return c.priKey;
|
}
|
|
/**
|
*
|
* @param path
|
* @param pwd
|
* @return
|
*/
|
public static String getCertIdByKeyStoreMap(String path, String pwd) {
|
Cert c = getSignCert(path, pwd);
|
if(c == null) return null;
|
return c.certId;
|
}
|
/**
|
*
|
* @param path
|
* @param pwd
|
* @return
|
*/
|
public static PrivateKey getSignCertPrivateKeyByStoreMap(String path, String pwd) {
|
Cert c = getSignCert(path, pwd);
|
if(c == null) return null;
|
return c.priKey;
|
}
|
|
// /**
|
// * 获取敏感信息加密证书的certId
|
// *
|
// * @return
|
// */
|
// public static String getEncryptCertId() {
|
// Cert c = getEncryptCert();
|
// if(c == null) return null;
|
// return c.certId;
|
// }
|
//
|
//
|
// public static PublicKey getEncryptCertPublicKey(){
|
// Cert c = getEncryptCert();
|
// if(c == null) return null;
|
// return c.pubKey;
|
// }
|
//
|
// /**
|
// * 获取6.0统一支付产品pin加密证书的certId
|
// *
|
// * @return
|
// */
|
// public static String getPinEncryptCertId() {
|
// Cert c = getPinEncryptCert();
|
// if(c == null) return null;
|
// return c.certId;
|
// }
|
//
|
//
|
// public static PublicKey getPinEncryptCertPublicKey(){
|
// Cert c = getEncryptCert();
|
// if(c == null) return null;
|
// return c.pubKey;
|
// }
|
|
/**
|
* 使用模和指数生成RSA公钥 注意:此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同
|
*
|
* @param modulus
|
* 模
|
* @param exponent
|
* 指数
|
* @return
|
*/
|
private static PublicKey getPublicKey(String modulus, String exponent) {
|
try {
|
BigInteger b1 = new BigInteger(modulus);
|
BigInteger b2 = new BigInteger(exponent);
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
|
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
|
return keyFactory.generatePublic(keySpec);
|
} catch (Exception e) {
|
logger.error("构造RSA公钥失败:" + e);
|
return null;
|
}
|
}
|
|
/**
|
* 将字符串转换为X509Certificate对象.
|
*
|
* @param x509CertString
|
* @return
|
*/
|
public static X509Certificate genCertificateByStr(String x509CertString) {
|
X509Certificate x509Cert = null;
|
try {
|
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
|
InputStream tIn = new ByteArrayInputStream(
|
x509CertString.getBytes("ISO-8859-1"));
|
x509Cert = (X509Certificate) cf.generateCertificate(tIn);
|
} catch (Exception e) {
|
logger.error("gen certificate error", e);
|
}
|
return x509Cert;
|
}
|
|
/**
|
* 从配置文件acp_sdk.properties中获取验签公钥使用的中级证书
|
* @return
|
*/
|
private static X509Certificate getMiddleCert() {
|
String path = SDKConfig.getConfig().getMiddleCertPath();
|
if (isEmpty(path)) {
|
logger.error("未配置中级证书时无法调用此方法。");
|
return null;
|
}
|
if(middleCert == null) {
|
initMiddleCert();
|
}
|
return middleCert;
|
}
|
|
/**
|
* 从配置文件acp_sdk.properties中获取验签公钥使用的根证书
|
* @return
|
*/
|
private static X509Certificate getRootCert() {
|
String path = SDKConfig.getConfig().getRootCertPath();
|
if (isEmpty(path)) {
|
logger.error("未配置根证书时无法调用此方法。");
|
return null;
|
}
|
if(rootCert == null) {
|
initRootCert();
|
}
|
return rootCert;
|
}
|
|
/**
|
* 获取证书的CN
|
* @param aCert
|
* @return
|
*/
|
public static String getIdentitiesFromCertficate(X509Certificate aCert) {
|
String tDN = aCert.getSubjectDN().toString();
|
String tPart = "";
|
if ((tDN != null)) {
|
String tSplitStr[] = tDN.substring(tDN.indexOf("CN=")).split("@");
|
if (tSplitStr != null && tSplitStr.length > 2
|
&& tSplitStr[2] != null)
|
tPart = tSplitStr[2];
|
}
|
return tPart;
|
}
|
|
/**
|
* 验证书链。
|
* @param cert
|
* @return
|
*/
|
public static boolean verifyCertificateChain(X509Certificate cert, X509Certificate middleCert, X509Certificate rootCert){
|
|
if (null == cert) {
|
logger.error("cert must Not null");
|
return false;
|
}
|
|
if (null == middleCert) {
|
logger.error("middleCert must Not null");
|
return false;
|
}
|
|
if (null == rootCert) {
|
logger.error("rootCert or cert must Not null");
|
return false;
|
}
|
|
try {
|
|
X509CertSelector selector = new X509CertSelector();
|
selector.setCertificate(cert);
|
|
Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
|
trustAnchors.add(new TrustAnchor(rootCert, null));
|
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(
|
trustAnchors, selector);
|
|
Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>();
|
intermediateCerts.add(rootCert);
|
intermediateCerts.add(middleCert);
|
intermediateCerts.add(cert);
|
|
pkixParams.setRevocationEnabled(false);
|
|
CertStore intermediateCertStore = CertStore.getInstance("Collection",
|
new CollectionCertStoreParameters(intermediateCerts), "BC");
|
pkixParams.addCertStore(intermediateCertStore);
|
|
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
|
|
@SuppressWarnings("unused")
|
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
|
.build(pkixParams);
|
logger.info("verify certificate chain succeed.");
|
return true;
|
} catch (java.security.cert.CertPathBuilderException e){
|
logger.error("verify certificate chain fail.", e);
|
} catch (Exception e) {
|
logger.error("verify certificate chain exception: ", e);
|
}
|
return false;
|
}
|
|
public static PublicKey verifyAndGetVerifyPubKey(String x509CertString){
|
|
if(isEmpty(x509CertString)) {
|
logger.error("验签公钥证书传了空。");
|
return null;
|
}
|
if(verifyCerts510.containsKey(x509CertString))
|
return verifyCerts510.get(x509CertString);
|
|
logger.debug("验签公钥证书:["+x509CertString+"]");
|
X509Certificate x509Cert = CertUtil.genCertificateByStr(x509CertString);
|
if (x509Cert == null) {
|
logger.error("convert signPubKeyCert failed");
|
return null;
|
}
|
// 验证证书链
|
if (!CertUtil.verifyCertificate(x509Cert)) {
|
logger.error("验证公钥证书失败,证书信息:[" + x509CertString + "]");
|
return null;
|
}
|
logger.info("验证公钥验证成功:[" + x509Cert.getSerialNumber().toString(10) + "]");
|
PublicKey publicKey = x509Cert.getPublicKey();
|
verifyCerts510.put(x509CertString, publicKey);
|
return publicKey;
|
}
|
|
/**
|
*
|
* @param cert
|
* @return
|
*/
|
private static boolean verifyCertificate(X509Certificate cert) {
|
|
if ( null == cert) {
|
logger.error("cert must Not null");
|
return false;
|
}
|
try {
|
cert.checkValidity();//验证有效期
|
if(!verifyCertificateChain(cert, CertUtil.getMiddleCert(), CertUtil.getRootCert())){
|
return false;
|
}
|
} catch (Exception e) {
|
logger.error("verifyCertificate fail", e);
|
return false;
|
}
|
|
if(SDKConfig.getConfig().isIfValidateCNName()){
|
// 验证公钥是否属于银联
|
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert))) {
|
logger.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert));
|
return false;
|
}
|
} else {
|
// 验证公钥是否属于银联
|
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert))
|
&& !"00040000:SIGN".equals(CertUtil.getIdentitiesFromCertficate(cert))) {
|
logger.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert));
|
return false;
|
}
|
}
|
return true;
|
}
|
|
/**
|
* 打印系统环境信息
|
*/
|
private static void printSysInfo() {
|
logger.info("================= SYS INFO begin====================");
|
logger.info("os_name:" + System.getProperty("os.name"));
|
logger.info("os_arch:" + System.getProperty("os.arch"));
|
logger.info("os_version:" + System.getProperty("os.version"));
|
logger.info("java_vm_specification_version:"
|
+ System.getProperty("java.vm.specification.version"));
|
logger.info("java_vm_specification_vendor:"
|
+ System.getProperty("java.vm.specification.vendor"));
|
logger.info("java_vm_specification_name:"
|
+ System.getProperty("java.vm.specification.name"));
|
logger.info("java_vm_version:"
|
+ System.getProperty("java.vm.version"));
|
logger.info("java_vm_name:" + System.getProperty("java.vm.name"));
|
logger.info("java.version:" + System.getProperty("java.version"));
|
logger.info("java.vm.vendor=[" + System.getProperty("java.vm.vendor") + "]");
|
logger.info("java.version=[" + System.getProperty("java.version") + "]");
|
printProviders();
|
logger.info("================= SYS INFO end=====================");
|
}
|
|
/**
|
* 打jre中印算法提供者列表
|
*/
|
private static void printProviders() {
|
logger.info("Providers List:");
|
Provider[] providers = Security.getProviders();
|
for (int i = 0; i < providers.length; i++) {
|
logger.info(i + 1 + "." + providers[i].getName());
|
}
|
}
|
|
/**
|
* 证书文件过滤器
|
*
|
*/
|
static class CerFilter implements FilenameFilter {
|
public boolean isCer(String name) {
|
return name.toLowerCase().endsWith(".cer");
|
}
|
public boolean accept(File dir, String name) {
|
return isCer(name);
|
}
|
}
|
|
public static Collection<PublicKey> getVerifySignPubKeys(){
|
return verifyCerts.values();
|
}
|
}
|