如何从其文件中获取证书类型?

How to get a certificate type from its file?

我有一个 X509Certificate,我想以编程方式确定其类型(扩展验证 (EV SSL)、组织验证 (OV SSL) 或域验证 (DV SSL))。

我使用 BouncyCastle cryptoAPI 读取了我的证书。例如,这就是我从文件中读取它并获取发行者和主题通用名称 (CN) 的方式:

...
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream input = new FileInputStream(certfile);                                  
X509Certificate cert = (X509Certificate)cf.generateCertificate(input);
X500Name x500name = new JcaX509CertificateHolder(cert).getSubject();
X500Name issuer = new JcaX509CertificateHolder(cert).getIssuer();
...

如何在我的程序中获取给定证书的类型?

从技术角度来看,证书类型没有区别。它更像是一种组织协议。

您可以检查证书主题(您调用的变量 x500name)。如果此字段包含密钥 jurisdictionOfIncorporationCountryNamebusinessCategory 的值,则您拥有 EV 证书。然后密钥 serialNumber 指向该商业实体的一些合法注册密钥(例如我们的德语 Handelsregisternummer),密钥 CN 是该商业实体的注册名称。

据我所知,DV 和 OV 之间的区别更多的是一种营销特征。

我正在使用 BouncyCastle 1.57。如果您使用的版本 < 1.47,代码可能会有所不同,因为在 1.47 中他们制作了 significant changes in the API(尽管想法相同)。

要检查证书是 DV 还是 OV,您可以检查 Certificate Policies extension, as explained in this answer and in GlobalSign's website:

Type                     Policy Identifier
Domain Validated         2.23.140.1.2.1
Organization Validated   2.23.140.1.2.2

Having these identifiers takes us a long way towards our goal of deterministic evaluation of certificate issuance policy — that said, not all CAs have yet adopted them.

请注意,此方法并非 100% 有保证,因为它并未被所有证书颁发机构完全采用。话虽这么说,您可以使用以下方法通过 BouncyCastle 检查此扩展:

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.x509.extension.X509ExtensionUtil;

X509Certificate cert = // get certificate

byte[] value = cert.getExtensionValue("2.5.29.32");
if (value != null) { // extension is present
    // CertificatePolicies is a sequence
    DLSequence seq = (DLSequence) X509ExtensionUtil.fromExtensionValue(value);
    for (int i = 0; i < seq.size(); i++) {
        // each element is also a sequence
        DLSequence s = (DLSequence) seq.getObjectAt(i);
        // first element is an OID
        String oid = ((ASN1ObjectIdentifier) s.getObjectAt(0)).getId();
        if ("2.23.140.1.2.1".equals(oid)) {
            // DV
        } else if ("2.23.140.1.2.2".equals(oid)) {
            // OV
        }
    }
}