如何使用JAVA检查X509Certificate链的撤销状态?

时间:2016-06-29 17:33:40

标签: 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是我创建的一个类,它将从文件导入证书,其方法将返回证书对象。它工作正常,最终证书打印得很好,如下所示:

  

[[版本:V3主题:CN = *。google.com,O = Google Inc,L = Mountain   View,ST = California,C = US签名算法:SHA256withRSA,OID =   1.2.840.113549.1.1.11

     

密钥:Sun EC公钥,256位公共x coord:   46177506158937302063723158048612066903199153823785912505310712817097913459047   public y coord:   113809014154880901150321029617294838083005712679903474974082163637608868220331   参数:secp256r1 [NIST P-256,X9.62 prime256v1]   (1.2.840.10045.3.1.7)有效期:[来自:2016年6月16日星期四14:07:32,                  致:2016年9月8日星期四13:59:00 IST 2016]发行人:CN = Google Internet Authority G2,O = Google Inc,C = US SerialNumber:[
  51e47ed1 28a4436e]

     

证书扩展: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
  .` ..]]

     

]算法:[SHA256withRSA]签名:0000:38 89 81 D8 57 DA 3C   C7 60 EA BA 6B 08 D4 92 47 8 ... W.&lt;。..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 ..&#34; C / .S ...... GD \ 0060:EF   16 7A 73 2F 37 CB 39 48 3C F2 87 C5 77 82 A0 ..zs / 7.9H&lt; ... 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&#39; .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 .......&#34; .Od ...。

     

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

我的问题是,当我在程序上运行时,它会给我以下错误。

  

线程中的异常&#34; main&#34;了java.lang.RuntimeException:   java.security.cert.CertPathValidatorException:证书没有   指定OCSP响应者   test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157)     在test_data.ImportAndTestCert.main(ImportAndTestCert.java:72)引起   by:java.security.cert.CertPathValidatorException:证书确实如此   没有指定OCSP响应者   sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135)     在   sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219)     在   sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140)     在   sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)     在   java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)     在   test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126)     ......还有1个

如果我发表评论Security.setProperty("ocsp.enable", "true");,则会出现以下错误:

  

线程中的异常&#34; main&#34;了java.lang.RuntimeException:   java.security.cert.CertPathValidatorException:无法确定   撤销地位   test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157)     在test_data.ImportAndTestCert.main(ImportAndTestCert.java:72)引起   by:java.security.cert.CertPathValidatorException:无法确定   撤销地位   sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135)     在   sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219)     在   sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140)     在   sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)     在   java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)     在   test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126)     ......还有1个

我在这里错过了什么吗?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

我发现了问题。

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

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

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

  

线程中的异常&#34; main&#34;了java.lang.RuntimeException:   java.security.cert.CertPathValidatorException:无法确定   

的撤销状态

  

线程中的异常&#34; main&#34;了java.lang.RuntimeException:   java.security.cert.CertPathValidatorException:证书没有   

指定OCSP响应者

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