All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alipay.v3.util.AntCertificationUtil Maven / Gradle / Ivy
package com.alipay.v3.util;
import com.google.common.base.Strings;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
import java.util.*;
/**
* 证书文件可信校验
*
* @author junying.wjy
* @version $Id: AntCertificationUtil.java, v 0.1 2019-07-29 下午04:46 junying.wjy Exp $
*/
public class AntCertificationUtil {
private static BouncyCastleProvider provider;
static {
provider = new BouncyCastleProvider();
Security.addProvider(provider);
}
/**
* 验证证书是否可信
*
* @param certContent 需要验证的目标证书或者证书链
* @param rootCertContent 可信根证书列表
*/
public static boolean isTrusted(String certContent, String rootCertContent) {
X509Certificate[] certificates;
try {
certificates = readPemCertChain(certContent);
} catch (Exception e) {
//读取证书失败
throw new RuntimeException(e);
}
List rootCerts = new ArrayList();
try {
X509Certificate[] certs = readPemCertChain(rootCertContent);
rootCerts.addAll(Arrays.asList(certs));
} catch (Exception e) {
//读取根证书失败
throw new RuntimeException(e);
}
return verifyCertChain(certificates, rootCerts.toArray(new X509Certificate[rootCerts.size()]));
}
/**
* 验证证书是否是信任证书库中证书签发的
*
* @param cert 目标验证证书
* @param rootCerts 可信根证书列表
* @return 验证结果
*/
private static boolean verifyCert(X509Certificate cert, X509Certificate[] rootCerts) {
try {
cert.checkValidity();
} catch (CertificateExpiredException e) {
//证书已经过期
return false;
} catch (CertificateNotYetValidException e) {
//证书未激活
return false;
}
Map subjectMap = new HashMap();
for (X509Certificate root : rootCerts) {
subjectMap.put(root.getSubjectDN(), root);
}
Principal issuerDN = cert.getIssuerDN();
X509Certificate issuer = subjectMap.get(issuerDN);
if (issuer == null) {
//证书链验证失败
return false;
}
try {
PublicKey publicKey = issuer.getPublicKey();
verifySignature(publicKey, cert);
} catch (Exception e) {
//证书链验证失败
return false;
}
return true;
}
/**
* 验证证书链是否是信任证书库中证书签发的
*
* @param certs 目标验证证书列表
* @param rootCerts 可信根证书列表
* @return 验证结果
*/
private static boolean verifyCertChain(X509Certificate[] certs, X509Certificate[] rootCerts) {
boolean sorted = sortByDn(certs);
if (!sorted) {
//证书链验证失败:不是完整的证书链
return false;
}
//先验证第一个证书是不是信任库中证书签发的
X509Certificate prev = certs[0];
boolean firstOK = verifyCert(prev, rootCerts);
if (!firstOK || certs.length == 1) {
return firstOK;
}
//验证证书链
for (int i = 1; i < certs.length; i++) {
try {
X509Certificate cert = certs[i];
try {
cert.checkValidity();
} catch (CertificateExpiredException e) {
//证书已经过期
return false;
} catch (CertificateNotYetValidException e) {
//证书未激活
return false;
}
verifySignature(prev.getPublicKey(), cert);
prev = cert;
} catch (Exception e) {
//证书链验证失败
return false;
}
}
return true;
}
private static void verifySignature(PublicKey publicKey, X509Certificate cert)
throws NoSuchProviderException, CertificateException, NoSuchAlgorithmException, InvalidKeyException,
SignatureException {
cert.verify(publicKey, provider.getName());
}
/**
* 将证书链按照完整的签发顺序进行排序,排序后证书链为:[issuerA, subjectA]-[issuerA, subjectB]-[issuerB, subjectC]-[issuerC, subjectD]...
*
* @param certs 证书链
* @return true:排序成功,false:证书链不完整
*/
private static boolean sortByDn(X509Certificate[] certs) {
//主题和证书的映射
Map subjectMap = new HashMap();
//签发者和证书的映射
Map issuerMap = new HashMap();
//是否包含自签名证书
boolean hasSelfSignedCert = false;
for (X509Certificate cert : certs) {
if (isSelfSigned(cert)) {
if (hasSelfSignedCert) {
return false;
}
hasSelfSignedCert = true;
}
Principal subjectDN = cert.getSubjectDN();
Principal issuerDN = cert.getIssuerDN();
subjectMap.put(subjectDN, cert);
issuerMap.put(issuerDN, cert);
}
List certChain = new ArrayList();
X509Certificate current = certs[0];
addressingUp(subjectMap, certChain, current);
addressingDown(issuerMap, certChain, current);
//说明证书链不完整
if (certs.length != certChain.size()) {
return false;
}
//将证书链复制到原先的数据
for (int i = 0; i < certChain.size(); i++) {
certs[i] = certChain.get(i);
}
return true;
}
/**
* 验证证书是否是自签发的
*
* @param cert 目标证书
* @return true;自签发,false;不是自签发
*/
private static boolean isSelfSigned(X509Certificate cert) {
return cert.getSubjectDN().equals(cert.getIssuerDN());
}
/**
* 向上构造证书链
*
* @param subjectMap 主题和证书的映射
* @param certChain 证书链
* @param current 当前需要插入证书链的证书,include
*/
private static void addressingUp(final Map subjectMap, List certChain,
final X509Certificate current) {
certChain.add(0, current);
if (isSelfSigned(current)) {
return;
}
Principal issuerDN = current.getIssuerDN();
X509Certificate issuer = subjectMap.get(issuerDN);
if (issuer == null) {
return;
}
addressingUp(subjectMap, certChain, issuer);
}
/**
* 向下构造证书链
*
* @param issuerMap 签发者和证书的映射
* @param certChain 证书链
* @param current 当前需要插入证书链的证书,exclude
*/
private static void addressingDown(final Map issuerMap, List certChain,
final X509Certificate current) {
Principal subjectDN = current.getSubjectDN();
X509Certificate subject = issuerMap.get(subjectDN);
if (subject == null) {
return;
}
if (isSelfSigned(subject)) {
return;
}
certChain.add(subject);
addressingDown(issuerMap, certChain, subject);
}
private static X509Certificate[] readPemCertChain(String cert) throws CertificateException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(cert.getBytes());
CertificateFactory factory = CertificateFactory.getInstance("X.509", provider);
Collection extends Certificate> certificates = factory.generateCertificates(inputStream);
return certificates.toArray(new X509Certificate[certificates.size()]);
}
/**
* 获取支付宝根证书序列号
*
* @param rootCertContent 支付宝根证书内容
* @return 支付宝根证书序列号
*/
public static String getRootCertSN(String rootCertContent) {
String rootCertSN = null;
try {
X509Certificate[] x509Certificates = readPemCertChain(rootCertContent);
MessageDigest md = MessageDigest.getInstance("MD5");
for (X509Certificate c : x509Certificates) {
if (c.getSigAlgOID().startsWith("1.2.840.113549.1.1")) {
md.update((c.getIssuerX500Principal().getName() + c.getSerialNumber()).getBytes());
String certSN = new BigInteger(1, md.digest()).toString(16);
//BigInteger会把0省略掉,需补全至32位
certSN = fillMD5(certSN);
if (Strings.isNullOrEmpty(rootCertSN)) {
rootCertSN = certSN;
} else {
rootCertSN = rootCertSN + "_" + certSN;
}
}
}
} catch (Exception e) {
//提取根证书失败
AlipayLogger.logBizError(e);
}
return rootCertSN;
}
/**
* 获取公钥证书序列号
*
* @param certContent 公钥证书内容
* @return 公钥证书序列号
*/
public static String getCertSN(String certContent) {
try {
InputStream inputStream = new ByteArrayInputStream(certContent.getBytes());
CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = (X509Certificate) factory.generateCertificate(inputStream);
return md5((cert.getIssuerX500Principal().getName() + cert.getSerialNumber()).getBytes());
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static String md5(byte[] bytes) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
String certSN = new BigInteger(1, md.digest()).toString(16);
//BigInteger会把0省略掉,需补全至32位
certSN = fillMD5(certSN);
return certSN;
}
private static String fillMD5(String md5) {
return md5.length() == 32 ? md5 : fillMD5("0" + md5);
}
/**
* 提取公钥证书中的公钥
*
* @param certContent 公钥证书内容
* @return 公钥证书中的公钥
*/
public static String getCertPublicKey(String certContent) {
try {
InputStream inputStream = new ByteArrayInputStream(certContent.getBytes());
CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = (X509Certificate) factory.generateCertificate(inputStream);
return Base64.toBase64String(cert.getPublicKey().getEncoded());
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 从文件中读取证书内容
*
* @param certPath 证书路径
* @return 证书内容
*/
public static String readCertContent(String certPath) {
if (existsInFileSystem(certPath)) {
return readFromFileSystem(certPath);
}
return readFromClassPath(certPath);
}
private static boolean existsInFileSystem(String certPath) {
try {
return new File(certPath).exists();
} catch (Throwable e) {
return false;
}
}
private static String readFromFileSystem(String certPath) {
try {
return new String(Files.toByteArray(new File(certPath)), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("从文件系统中读取[" + certPath + "]失败," + e.getMessage(), e);
}
}
private static String readFromClassPath(String certPath) {
try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(certPath)) {
return new String(ByteStreams.toByteArray(inputStream), StandardCharsets.UTF_8);
} catch (Exception e) {
String errorMessage = e.getMessage() == null ? "" : e.getMessage() + "。";
if (certPath.startsWith("/")) {
errorMessage += "ClassPath路径不可以/开头,请去除后重试。";
}
throw new RuntimeException("读取[" + certPath + "]失败。" + errorMessage, e);
}
}
}