0

I have the following task when to achieve, but there seems not a good way on the web showing how to do it gracefully. (Either the solution is using the old HTTPClient or the solution is simply not very related) Can someone provide any advices or solution on that?

Given an url, my app needs to fetch the associated TLS server certificate and do the following tasks.

  1. Retrieve the subject field in the certificate
  2. Check the TLS server certificate is not expired
  3. Check the TLS server certificate is valid by making query to the Issuing CA's OCSP service.

HttpURLConnection and URLConnection seem to be related to the task I'm trying to complete, but it's not sure how to retrieve the server certificate.

I'm aware of the following sites about server certificate in Android

http://www.normalesup.org/~george/articles/manual_https_cert_check_on_android.html

Receive & Validate certificate from server HTTPS - android

Stephen Fong
  • 697
  • 5
  • 17

1 Answers1

0

It turns out you can use getServerCertificates() to retrieve the certificates chain which is fetched after you started a HttpsURLConnection. TLS is implemented by HttpsURLConnection so that you can confirm the certificates are real and your communication with the server is confidential, data integrity is preserved.

public void verifyCertificate(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("DEBUG", "Hello there");
                try {
                    aFunctionWithCoolName("https://urlOfTheSiteYouWannaCheck.com");
                    Log.d("DEBUG", "Executed aFancyFunctionWithCoolName without any exceptions");
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.d("DEBUG", "IOException");
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                    Log.d("DEBUG", "NoSuchAlgorithmException");
                } catch (CertificateEncodingException e) {
                    e.printStackTrace();
                    Log.d("DEBUG", "CertificateEncodingException");
                } catch (CertificateParsingException e) {
                    e.printStackTrace();
                    Log.d("DEBUG", "CertificateParsingException");
                } catch (Exception e) {
                    Log.wtf("DEBUG", "Too sad, I don't know what is happening :(");
                }
            }
        }).start();
    }

    private static void aFunctionWithCoolName(String httpsURL) throws IOException, NoSuchAlgorithmException, CertificateEncodingException, CertificateParsingException {

        final HttpsURLConnection con = (HttpsURLConnection) (new URL(httpsURL)).openConnection();

        con.setRequestMethod("GET");
        con.setConnectTimeout(5000);

        con.connect();

        // https://developer.android.com/reference/java/security/cert/X509Certificate
        // https://developer.android.com/reference/java/security/cert/Certificate
        // https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection#getServerCertificates()

        final Certificate[] certs = con.getServerCertificates();
        final Certificate subjectCert = certs[0];
        final Certificate rootCert = certs[certs.length-1];
        if (subjectCert instanceof X509Certificate && rootCert instanceof X509Certificate) {
            X509Certificate sc = (X509Certificate) subjectCert;
            X509Certificate rc = (X509Certificate) rootCert;
            printX509CertificateDetail(sc);

        }
    }

    public static void printX509CertificateDetail(X509Certificate cert) {
        Log.d("DEBUG", "===========================================");
        Log.d("DEBUG - Subject DN", cert.getSubjectX500Principal().toString());
        Log.d("DEBUG - Subject CN", getSubjectCommonName(cert));
        Log.d("DEBUG - URL DN", url.getHost());
        Log.d("DEBUG - Issuer DN", cert.getIssuerDN().toString());
        Log.d("DEBUG - Not After", cert.getNotAfter().toString());
        Log.d("DEBUG - Not Before", cert.getNotBefore().toString());
    }
Stephen Fong
  • 697
  • 5
  • 17