求OpenSSL命令openssl verify -CAfile cert1.pem cert2.pem的BouncyCastle等价实现
等价于
openssl verify -CAfile cert1.pem cert2.pem的Java实现方案 当然有啦!不管是用BouncyCastle还是JDK自带的API,都能实现和这条OpenSSL命令完全一致的证书验证逻辑——也就是用指定的CA证书(cert1.pem)作为信任锚,验证目标证书(cert2.pem)是否由该CA合法签发、证书状态有效。下面给你具体的实现方案:
BouncyCastle实现方案
BouncyCastle对PEM格式的证书处理更友好,不需要手动解析头部尾部,步骤也很清晰:
首先要确保项目引入了BouncyCastle的核心依赖(比如Maven中添加bcprov-jdk15on和bcpkix-jdk15on),然后用以下代码实现:
import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.openssl.PEMParser; import java.io.FileReader; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.PKIXParameters; import java.security.KeyStore; import java.util.Collections; public class BcCertVerify { public static void main(String[] args) throws Exception { // 1. 加载CA信任证书(对应OpenSSL的-CAfile参数) PEMParser caParser = new PEMParser(new FileReader("cert1.pem")); X509CertificateHolder caCertHolder = (X509CertificateHolder) caParser.readObject(); X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(caCertHolder); caParser.close(); // 2. 加载待验证的目标证书 PEMParser targetParser = new PEMParser(new FileReader("cert2.pem")); X509CertificateHolder targetCertHolder = (X509CertificateHolder) targetParser.readObject(); X509Certificate targetCert = new JcaX509CertificateConverter().getCertificate(targetCertHolder); targetParser.close(); // 3. 构建信任库,把CA证书加入信任锚 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); trustStore.setCertificateEntry("trusted-ca", caCert); // 4. 配置验证参数:和OpenSSL默认行为一致,关闭吊销检查 PKIXParameters params = new PKIXParameters(trustStore); params.setRevocationEnabled(false); // 5. 执行证书验证 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); certFactory.generateCertificatePath(Collections.singletonList(targetCert)).validate(params); System.out.println("证书验证通过!"); } }
这段代码完全对应OpenSSL命令的逻辑:用cert1.pem作为唯一的信任锚,验证cert2.pem的签名有效性、有效期、证书链(这里是直接由CA签发的单证书链)。如果验证失败,会抛出对应的证书异常(比如签名不匹配、证书过期等)。
JDK原生实现方案
如果不想引入第三方库,JDK自带的java.security.cert包也能实现同样的功能,而且JDK的CertificateFactory已经支持直接读取标准PEM格式的证书:
import java.io.FileInputStream; import java.io.InputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.PKIXParameters; import java.security.KeyStore; import java.util.Collections; public class JdkCertVerify { public static void main(String[] args) throws Exception { // 加载CA证书和目标证书 X509Certificate caCert = loadX509Cert("cert1.pem"); X509Certificate targetCert = loadX509Cert("cert2.pem"); // 构建信任库 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); trustStore.setCertificateEntry("trusted-ca", caCert); // 配置验证参数,关闭吊销检查(匹配OpenSSL默认) PKIXParameters params = new PKIXParameters(trustStore); params.setRevocationEnabled(false); // 执行验证 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); certFactory.generateCertificatePath(Collections.singletonList(targetCert)).validate(params); System.out.println("证书验证通过!"); } // 工具方法:读取PEM格式的X.509证书 private static X509Certificate loadX509Cert(String filePath) throws Exception { try (InputStream inputStream = new FileInputStream(filePath)) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (X509Certificate) certFactory.generateCertificate(inputStream); } } }
额外注意点
- 如果目标证书是由中间CA签发的,你需要把整个证书链(目标证书+中间CA证书)都传入
generateCertificatePath的列表中,和OpenSSL命令中指定中间链的逻辑一致。 - 如果需要开启证书吊销检查(对应OpenSSL的
-CRLfile参数),可以把params.setRevocationEnabled(true),同时需要配置CRL的获取源(比如通过证书的CRL分发点)。
内容的提问来源于stack exchange,提问作者rocky
相关产品推荐
相关产品推荐

