20

I need to create an Https connection with a remote server then retrieve and verify the certificate.

I have established the connection fine:

try {  
    url = new URL(this.SERVER_URL);  
    HttpURLConnection con = (HttpURLConnection) url.openConnection();   
    HttpsURLConnection secured = (HttpsURLConnection) con;  
    secured.connect(); 
}  

But it seems getServerCertificateChain() method is undefined by the type HttpsURLConnection.

So how do I retrieve the server certificate chain? My understanding is that getServerCertificateChain() should return an array of X509Certificate objects and that this class has methods I can use to interrogate the certificate.

I need to verify that:

  1. the certificate is valid and trusted,
  2. check the Certificate Revocation List Distribution Point against the certificate serial number
  3. make sure it isn't expired and
  4. check that the URL in the certificate is matches another (which I already have retrieved ).

I'm lost and would really appreciate any help!

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
Marc H
  • 1,228
  • 3
  • 18
  • 29

3 Answers3

33

The method you want is getServerCertificates, not getServerCertificateChain. There is some nice sample code here.


EDIT

Added some sample code of my own. Good starting point for you. Don't forget to look at the Javadocs for HttpsURLConnection and X509Certificate.

import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;

public class TestSecuredConnection {

    /**
     * @param args
     */
    public static void main(String[] args) {
        TestSecuredConnection tester = new TestSecuredConnection();
        try {
            tester.testConnectionTo("https://www.google.com");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public TestSecuredConnection() {
        super();
    }

    public void testConnectionTo(String aURL) throws Exception {
        URL destinationURL = new URL(aURL);
        HttpsURLConnection conn = (HttpsURLConnection) destinationURL
                .openConnection();
        conn.connect();
        Certificate[] certs = conn.getServerCertificates();
        for (Certificate cert : certs) {
            System.out.println("Certificate is: " + cert);
            if(cert instanceof X509Certificate) {
                try {
                    ( (X509Certificate) cert).checkValidity();
                    System.out.println("Certificate is active for current date");
                } catch(CertificateExpiredException cee) {
                    System.out.println("Certificate is expired");
                }
            }
        }
    }
}
Perception
  • 79,279
  • 19
  • 185
  • 195
  • Thank you -- I am coding to spec from a large corporations manual and I was beginning to suspect that whoever wrote this section had erred. I'm a neophyte though when it comes to java networking so I've been spending hours trying to figure what the hell the difference is between getServerCertificateChain and getServerCertificates. – Marc H Aug 26 '11 at 03:33
  • How do I interrogate the certificates though as per the four requirements I listed above? – Marc H Aug 26 '11 at 03:34
  • You will have to convert the certificates to X509Certificates and use the methods on that class. – Perception Aug 26 '11 at 11:03
  • How do I retrieve the url in the certificate? How do I check if it is valid and trusted and not expired? I am a networking neophyte and I'm finding most resources on the net only add to my confusion. – Marc H Aug 26 '11 at 19:47
  • Did you look at the Javadocs for X509Certificate? It has a lot of the methods you are looking for. You're going to have to do some reading, also look at addition to my answer above. – Perception Aug 26 '11 at 20:21
  • I am confused though because X509Certificate is an abstract class and some it's methods like checkValidity() are as well. I am looking at X509TrustManager as well and there is a method, checkClientTrusted but I run into the same question with that interface as well. Is there a tutorial or any articles you can recommend to point me in the right direction? – Marc H Aug 26 '11 at 21:25
  • Wow.. somehow I didn't see the sample code you wrote when I made that comment. Guess I need to catch up on my sleep :) Thanks!!! – Marc H Aug 26 '11 at 21:46
  • That was extremely helpful - all I need to do now is figure out how to extract the url from the certificate. – Marc H Aug 26 '11 at 21:51
  • 3
    **Warning**: the code above does **not** fully validate the chain, it only checks if the certificate is within its validity period. – Maarten Bodewes May 28 '17 at 17:21
  • This code only lets you examine the certificates if they are accepted. The call to getServerCertificates will return null if the certs are not trusted. – Matt__C Oct 19 '17 at 15:02
2

Quick googling brought me to this example using BouncyCastle. I think it better answers the question. http://www.nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/

Kirby
  • 15,127
  • 10
  • 89
  • 104
  • 3
    code not formatted properly in that blog.. Here is the source code https://svn.apache.org/repos/asf/cxf/tags/cxf-2.4.1/distribution/src/main/release/samples/sts_issue_operation/src/main/java/demo/sts/provider/cert/ – arulraj.net Mar 03 '16 at 07:23
1

This sample code mentioned by Kirby and arulraj.net has been removed from Apache CXF in 2011 and did not support OCSP. The Apache PDFBox project "resurrected" this code and added OCSP support and more features that were missing in the original code, e.g. CRL signature check. Since release 2.0.13 the improved source code is available in the examples subproject, in the CertificateVerifier class. It is also available online with small improvements.

The code is not claiming to be perfect, and does not yet check whether the root is trusted. Development is tracked in JIRA issue PDFBOX-3017.

Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97