如何在Java中从.cer证书文件提取包含终端实体、CA、根证书的完整证书链
Java获取.cer文件完整证书链实现方案
你提到的打开.cer即可查看完整证书链的效果如下图:
根据你的证书存储格式不同,可以选择以下两种实现方式:
方案1:读取自带完整链的PKCS7格式.cer文件
如果你的.cer文件本身已经打包了完整证书链(即打开后直接能看到所有层级证书的场景,这类证书大多以PKCS#7格式存储证书集合),直接用JDK自带的CertificateFactory读取全部证书即可,不需要额外构建,代码如下:
import java.io.FileInputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.List; public class CertChainReader { public static void main(String[] args) throws Exception { // 替换为你的证书实际路径 String certPath = "C:\\Users\\grish\\Desktop\\certificateForValidation.cer"; FileInputStream fis = new FileInputStream(certPath); // 初始化X.509类型的证书工厂 CertificateFactory cf = CertificateFactory.getInstance("X.509"); // 读取文件内所有证书,返回集合即为完整证书链,包含终端实体、中间CA、根CA证书 List<X509Certificate> certChain = (List<X509Certificate>) cf.generateCertificates(fis); // 遍历打印验证证书信息 for (X509Certificate cert : certChain) { System.out.println("证书主题:" + cert.getSubjectDN()); System.out.println("证书颁发者:" + cert.getIssuerDN() + "\n"); } fis.close(); } }
方案2:单终端证书自动构建完整信任链
如果你的.cer文件内仅存储了终端实体证书,需要和信任根库结合自动构建完整证书链,对应C#中X509Chain.Build的能力,可以用JDK自带的CertPathBuilder实现,还支持自定义吊销校验等策略,代码如下:
import java.io.FileInputStream; import java.security.KeyStore; import java.security.cert.*; import java.util.Collections; import java.util.List; public class CertChainBuilder { public static void main(String[] args) throws Exception { // 1. 读取终端实体证书 String certPath = "C:\\Users\\grish\\Desktop\\certificateForValidation.cer"; FileInputStream fis = new FileInputStream(certPath); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate targetCert = (X509Certificate) cf.generateCertificate(fis); fis.close(); // 2. 加载JDK默认信任根证书库,也可以替换为自定义信任库 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); // JDK默认信任库密码为changeit FileInputStream tsFis = new FileInputStream(System.getProperty("java.home") + "/lib/security/cacerts"); trustStore.load(tsFis, "changeit".toCharArray()); tsFis.close(); // 3. 配置证书链构建参数 PKIXBuilderParameters buildParams = new PKIXBuilderParameters(trustStore, new X509CertSelector()); // 开启在线吊销校验,对应C#的X509RevocationMode.Online,不需要可设为false buildParams.setRevocationEnabled(true); // 将待校验的终端证书加入证书源 CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Collections.singletonList(targetCert))); buildParams.addCertStore(certStore); // 4. 执行证书链构建 CertPathBuilder pathBuilder = CertPathBuilder.getInstance("PKIX"); PKIXCertPathBuilderResult buildResult = (PKIXCertPathBuilderResult) pathBuilder.build(buildParams); // 获取构建好的证书链,追加信任根证书得到完整链 List<X509Certificate> fullCertChain = (List<X509Certificate>) buildResult.getCertPath().getCertificates(); fullCertChain.add(buildResult.getTrustAnchor().getTrustedCert()); // 遍历打印验证证书信息 for (X509Certificate cert : fullCertChain) { System.out.println("证书主题:" + cert.getSubjectDN()); System.out.println("证书颁发者:" + cert.getIssuerDN() + "\n"); } } }
注意事项
- 你原代码中使用的
X509CertImpl是Sun/Oracle JDK的内部专用API,跨JDK版本兼容性差,推荐使用标准的CertificateFactory读取证书 - 如果你的证书链包含非系统默认信任的根证书,需要提前将根证书导入到信任库,或者传入自定义的信任库作为构建参数即可
内容的提问来源于stack exchange,提问作者Grisha Pipoyan
相关产品推荐
相关产品推荐

