title: How to check revocation status of X509Certificate chain using JAVA?
body: <p>I am having a chain of X509Certificates starting with user certificate and ending with trusted CA certificate. For the test, I am experimenting with Google certificates.</p>
  
  <p>I want to check the revocation status of every certificate in Certificate chain.</p>
  
  <p>I am using following code:</p>
  
  <pre><code>public static boolean isCertChainValid(ArrayList&lt;X509Certificate&gt; 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);
      }
  }
  </code></pre>
  
  <p>This is how I get list of certificates:</p>
  
  <pre><code>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&lt;X509Certificate&gt; cList = new ArrayList&lt;&gt;();
      cList.add(cert);
      cList.add(int_cert);
      cList.add(root_cert);
  
      System.out.println(isCertChainValid(cList));
  }
  </code></pre>
  
  <p>google.pem, google.int.pem, google.root.pem are the end, intermediate and root certificates respectively obtained using the export option in browser.</p>
  
  <p>CertVal is a class made by me that will import certificate from file and its method will return certificate object. It is working fine and end certificate is nicely printed as shown below:</p>
  
  <blockquote>
    <p>[ [   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</p>
    
    <p>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: [<br>
    51e47ed1 28a4436e]</p>
    
    <p>Certificate Extensions: 9 [1]: ObjectId: 1.3.6.1.5.5.7.1.1
    Criticality=false AuthorityInfoAccess [   [    accessMethod: caIssuers
    accessLocation: URIName: <a href="http://pki.google.com/GIAG2.crt" rel="nofollow">http://pki.google.com/GIAG2.crt</a> ,<br>
    accessMethod: ocsp    accessLocation: URIName:
    <a href="http://clients1.google.com/ocsp" rel="nofollow">http://clients1.google.com/ocsp</a> ] ]</p>
    
    <p>[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<br>
    .Z./ ] ]</p>
    
    <p>[3]: ObjectId: 2.5.29.19 Criticality=true BasicConstraints:[<br>
    CA:false   PathLen: undefined ]</p>
    
    <p>[4]: ObjectId: 2.5.29.31 Criticality=false CRLDistributionPoints [<br>
    [DistributionPoint:
         [URIName: <a href="http://pki.google.com/GIAG2.crl]" rel="nofollow">http://pki.google.com/GIAG2.crl]</a> ]]</p>
    
    <p>[5]: ObjectId: 2.5.29.32 Criticality=false CertificatePolicies [<br>
    [CertificatePolicyId: [1.3.6.1.4.1.11129.2.5.1] []  ]<br>
    [CertificatePolicyId: [2.23.140.1.2.2] []  ] ]</p>
    
    <p>[6]: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [<br>
    serverAuth   clientAuth ]</p>
    
    <p>[7]: ObjectId: 2.5.29.15 Criticality=false KeyUsage [<br>
    DigitalSignature ]</p>
    
    <p>[8]: ObjectId: 2.5.29.17 Criticality=false SubjectAlternativeName [<br>
    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<br>
    DNSName: *.google.hu   DNSName: *.google.it   DNSName: *.google.nl<br>
    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<br>
    DNSName: www.goo.gl   DNSName: youtu.be   DNSName: youtube.com<br>
    DNSName: youtubeeducation.com ]</p>
    
    <p>[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<br>
    .`.. ] ]</p>
    
    <p>]   Algorithm: [SHA256withRSA]   Signature: 0000: 38 89 81 D8 57 DA 3C
    C7   60 EA BA 6B 08 D4 92 47  8...W.&lt;.<code>..k...G 0010: 60 AA B1 4B 39 34
    1C E4   7B CC 71 1F 28 8F 07 82</code>..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..<code>'..(..!/e1. 0040: A5 7D D6
    D4 86 89 27 7F   F6 3B 28 D6 16 AA 60 31  ......'..;(...</code>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&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'.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... .</p>
    
    <p>]</p>
  </blockquote>
  
  <p>As it is seen in Certificate Exceptions 9:[1] and [2], OSCP URL and CRL URL both are available with certificate. Both these things are there in intermediate certificate too but they are not there in root certificate which is justifiable since they are not needed with them.</p>
  
  <p>My problem is when I run above program, it gives me following error.</p>
  
  <blockquote>
    <p>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</p>
  </blockquote>
  
  <p>If I comment <code>Security.setProperty("ocsp.enable", "true");</code>, it is giving me following error:</p>
  
  <blockquote>
    <p>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</p>
  </blockquote>
  
  <p>Am I missing something here?</p>
  
  <p>Thanks for helping.</p>