java - 如何使用JAVA检查X509证书链的吊销状态?

标签 java security ssl certificate x509certificate

我有一个 X509Certificates 链,从用户证书开始到受信任的 CA 证书结束。为了进行测试,我正在尝试使用 Google 证书。

我想检查证书链中每个证书的吊销状态。

我正在使用以下代码:

public static boolean isCertChainValid(ArrayList<X509Certificate> certificateList) {

    try {

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

        CertPath certPath = certificateFactory.generateCertPath(certificateList);

        CertPathValidator validator = CertPathValidator.getInstance("PKIX");

        KeyStore keystore = KeyStore.getInstance("JKS");
        InputStream is = new FileInputStream(System.getProperty("java.home") + "/lib/security/" + "cacerts");
        keystore.load(is, "changeit".toCharArray());

        PKIXParameters params = new PKIXParameters(keystore);

        params.setRevocationEnabled(true);

        Security.setProperty("ocsp.enable", "true");
        System.setProperty("com.sun.net.ssl.checkRevocation", "true");
        System.setProperty("com.sun.security.enableCRLDP", "true");

        PKIXCertPathValidatorResult r = (PKIXCertPathValidatorResult) validator.validate(certPath, params);
        return true;
    } catch (CertificateException e) {
        throw new RuntimeException(e);

    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);

    } catch (KeyStoreException e) {
        throw new RuntimeException(e);

    } catch (IOException e) {
        throw new RuntimeException(e);

    } catch (InvalidAlgorithmParameterException e) {
        throw new RuntimeException(e);

    } catch (CertPathValidatorException e) {
        throw new RuntimeException(e);
    }
}

这是我获取证书列表的方式:

public static void main(String args[]) throws Exception {

    CertVal certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.pem"), "X.509");
    X509Certificate cert = (X509Certificate) certVal.getCert();

    certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.int.pem"), "X.509");
    X509Certificate int_cert = (X509Certificate) certVal.getCert();

    certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.root.pem"), "X.509");
    X509Certificate root_cert = (X509Certificate) certVal.getCert();

    System.out.println(cert.toString());

    ArrayList<X509Certificate> cList = new ArrayList<>();
    cList.add(cert);
    cList.add(int_cert);
    cList.add(root_cert);

    System.out.println(isCertChainValid(cList));
}

google.pem、google.int.pem、google.root.pem分别是使用浏览器中的导出选项获得的最终证书、中间证书和根证书。

CertVal 是我制作的一个类,它将从文件中导入证书,其方法将返回证书对象。它工作正常,最终证书打印得很好,如下所示:

[ [ Version: V3 Subject: CN=*.google.com, O=Google Inc, L=Mountain View, ST=California, C=US Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

Key: Sun EC public key, 256 bits public x coord: 46177506158937302063723158048612066903199153823785912505310712817097913459047 public y coord: 113809014154880901150321029617294838083005712679903474974082163637608868220331 parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7) Validity: [From: Thu Jun 16 14:07:32 IST 2016, To: Thu Sep 08 13:59:00 IST 2016] Issuer: CN=Google Internet Authority G2, O=Google Inc, C=US SerialNumber: [
51e47ed1 28a4436e]

Certificate Extensions: 9 [1]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false AuthorityInfoAccess [ [ accessMethod: caIssuers accessLocation: URIName: http://pki.google.com/GIAG2.crt ,
accessMethod: ocsp accessLocation: URIName: http://clients1.google.com/ocsp ] ]

[2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [ KeyIdentifier [ 0000: 4A DD 06 16 1B BC F6 68 B5 76 F5 81 B6 BB 62 1A J......h.v....b. 0010: BA 5A 81 2F
.Z./ ] ]

[3]: ObjectId: 2.5.29.19 Criticality=true BasicConstraints:[
CA:false PathLen: undefined ]

[4]: ObjectId: 2.5.29.31 Criticality=false CRLDistributionPoints [
[DistributionPoint: [URIName: http://pki.google.com/GIAG2.crl] ]]

[5]: ObjectId: 2.5.29.32 Criticality=false CertificatePolicies [
[CertificatePolicyId: [1.3.6.1.4.1.11129.2.5.1] [] ]
[CertificatePolicyId: [2.23.140.1.2.2] [] ] ]

[6]: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [
serverAuth clientAuth ]

[7]: ObjectId: 2.5.29.15 Criticality=false KeyUsage [
DigitalSignature ]

[8]: ObjectId: 2.5.29.17 Criticality=false SubjectAlternativeName [
DNSName: *.google.com DNSName: *.android.com DNSName: *.appengine.google.com DNSName: *.cloud.google.com DNSName: *.google-analytics.com DNSName: *.google.ca DNSName: *.google.cl DNSName: *.google.co.in DNSName: *.google.co.jp DNSName: *.google.co.uk DNSName: *.google.com.ar DNSName: *.google.com.au DNSName: *.google.com.br DNSName: *.google.com.co DNSName: *.google.com.mx DNSName: *.google.com.tr DNSName: *.google.com.vn DNSName: *.google.de DNSName: *.google.es DNSName: *.google.fr
DNSName: *.google.hu DNSName: *.google.it DNSName: *.google.nl
DNSName: *.google.pl DNSName: *.google.pt DNSName: *.googleadapis.com DNSName: *.googleapis.cn DNSName: *.googlecommerce.com DNSName: *.googlevideo.com DNSName: *.gstatic.cn DNSName: *.gstatic.com DNSName: *.gvt1.com DNSName: *.gvt2.com DNSName: *.metric.gstatic.com DNSName: *.urchin.com DNSName: *.url.google.com DNSName: *.youtube-nocookie.com DNSName: *.youtube.com DNSName: *.youtubeeducation.com DNSName: *.ytimg.com DNSName: android.clients.google.com DNSName: android.com DNSName: g.co DNSName: goo.gl DNSName: google-analytics.com DNSName: google.com DNSName: googlecommerce.com DNSName: urchin.com
DNSName: www.goo.gl DNSName: youtu.be DNSName: youtube.com
DNSName: youtubeeducation.com ]

[9]: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: EE 4B 83 40 44 28 0A 6A 01 4D 55 D0 A4 A7 5F 1E .K.@D(.j.MU..._. 0010: DF 60 F2 1E
.`.. ] ]

] Algorithm: [SHA256withRSA] Signature: 0000: 38 89 81 D8 57 DA 3C C7 60 EA BA 6B 08 D4 92 47 8...W.<...k...G 0010: 60 AA B1 4B 39 34 1C E4 7B CC 71 1F 28 8F 07 82..K94....q.(... 0020: D7 04 3F CC 12 B7 9E DF 9F 13 D4 5A 5A 30 31 1F ..?........ZZ01. 0030: A5 41 BE 9A 60 27 EE AF 28 A8 BC 21 2F 65 31 BF .A..'..(..!/e1. 0040: A5 7D D6 D4 86 89 27 7F F6 3B 28 D6 16 AA 60 31 ......'..;(...1 0050: 3D CD 67 97 84 22 43 2F B0 53 84 87 8C 47 44 5C =.g.."C/.S...GD\ 0060: EF 16 7A 73 2F 37 CB 39 48 3C F2 87 C5 77 82 A0 ..zs/7.9H<...w.. 0070: 08 84 2C 18 C6 A8 9C 57 5F 2B CC 9B 4F 7A 72 87 ..,....W_+..Ozr. 0080: C1 19 BC 0B 98 8B 09 1E 1D B1 5A BB 34 B6 95 1E ..........Z.4... 0090: B9 37 27 5C C4 73 DB AE 68 B7 B1 F9 E7 4D BB 75 .7'.s..h....M.u 00A0: 0B CE 16 75 B0 48 F2 39 AC DB 7C 68 C2 13 16 82 ...u.H.9...h.... 00B0: D2 E8 A8 F2 C1 D4 45 69 2C 8E D0 D4 FB 3D 74 7D ......Ei,....=t. 00C0: 02 CF 7C D6 17 64 63 9A E6 3B 8D F4 93 62 58 56 .....dc..;...bXV 00D0: 49 F8 0D 28 15 BC C5 B1 0F 66 1C 19 DF 83 A5 94 I..(.....f...... 00E0: 1C 2F 6A E1 A2 31 A1 23 C8 07 F8 09 BF A1 9A E4 ./j..1.#........ 00F0: EB E8 1A 7C 9D 89 CF 22 8A 4F 64 CC 8F D7 20 BD .......".Od... .

]

如证书异常(exception) 9:[1] 和 [2] 中所示,OSCP URL 和 CRL URL 都可用于证书。这些东西也存在于中间证书中,但它们不存在于根证书中,这是合理的,因为它们不需要它们。

我的问题是当我运行上述程序时,出现以下错误。

Exception in thread "main" java.lang.RuntimeException: java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder at test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157) at test_data.ImportAndTestCert.main(ImportAndTestCert.java:72) Caused by: java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) at test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126) ... 1 more

如果我评论 Security.setProperty("ocsp.enable", "true");,它会给我以下错误:

Exception in thread "main" java.lang.RuntimeException: java.security.cert.CertPathValidatorException: Could not determine revocation status at test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157) at test_data.ImportAndTestCert.main(ImportAndTestCert.java:72) Caused by: java.security.cert.CertPathValidatorException: Could not determine revocation status at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219) at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) at test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126) ... 1 more

我是不是漏掉了什么?

感谢您的帮助。

最佳答案

我发现了问题。

造成所有麻烦的是 certpath 中根证书的存在。

根证书不包含 CRL 和 OSCP 链接。 Trusted Certificate Repository 或 TrustStore 的工作是不断更新存储库。

由于根证书不包含 CRL 和 OSCP 链接,因此会出现如下错误

Exception in thread "main" java.lang.RuntimeException: java.security.cert.CertPathValidatorException: Could not determine revocation status at

Exception in thread "main" java.lang.RuntimeException: java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder at

简而言之,要检查证书链中证书的吊销状态,需要排除根证书。 Validator 算法可以确定最后一个中间证书是否由根 CA 签名。

关于java - 如何使用JAVA检查X509证书链的吊销状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38106503/

相关文章:

java - 有人能解释一下为什么这个 While 语句必须是 AND

java - Linux下OpenCV 2.8.4安装进行Java开发

关于标签 "access-denied-page"cvc-complex-type.3.2.2 : Attribute 'access-denied-page' is not allowed to appear 的 spring 安全警告

ssl - 如何向 Kafka Websocket 代理服务器开放安全 Websocket (WSS)

ssl - 自签名证书和 HTTPS 错误

java - Spring Executors - 在具有特定索引的线程中执行方法

java - 如果文件不存在,readAllLines 会返回什么?

security - 是否真的需要电子邮件地址验证来验证新用户?

php - 如何安全使用PHP Runkit_Sandbox

c# - 如何强制第三方服务尊重安全?