1

Here there is an example for custom SSL:
https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java

/**
 * This example demonstrates how to create secure connections with a custom SSL
 * context.
 */
public class ClientCustomSSL {

public final static void main(String[] args) throws Exception {
    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts.custom()
            .loadTrustMaterial(new File("my.keystore"), "nopassword".toCharArray(),
                    new TrustSelfSignedStrategy())
            .build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://httpbin.org/");

        System.out.println("Executing request " + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}
}

Why we need that? I've tested an HttpClient request without any SSL thing on it and I'm getting the correct response from HTTPS urls without errors.
What is the problem if I don't add any SSLContext?
And if it's important to make it more secure, what is this line?:

.loadTrustMaterial(new File("my.keystore"), "nopassword".toCharArray(),

it seems we need some file and also some password?

2
  • The example uses a keystore, which means it is doing client authentication. Evidently either your server didn't ask for a client certificate or didn't mind when you didn't send one because you hadn't configured a keystore. Commented Jul 4, 2018 at 1:02
  • @EJP: the code is using a file named keystore, and apparently in a keystore format (because it is read as such without throwing an exception), but it uses the contents as trust material, i.e. as a truststore, to authenticate the server. For Apache httpclient to do client auth, you call (one of the overloads of) SSLContextBuilder.loadKeyMaterial Commented Jul 5, 2018 at 8:55

1 Answer 1

4

If you don't specify (a factory using) a context, Java (JSSE) uses a default context containing the default truststore, which defaults to the file JRE/lib/security/cacerts (or jssecacerts if present) unless overridden with system properties; see https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores . Depending on whether you are using an Oracle-was-Sun Java package, an IBM or Apple package or Android system, or OpenJDK, this default truststore usually contains more or less the same set of public CAs as most OSes and browsers, like Verisign Symantec Digicert and GoDaddy and LetsEncrypt/Identrust. Whether you consider the default cacerts 'secure' is a choice for you to make; if not you can either change the contents of the default file, or have your code use a different file and to do the latter yes you must specify the filename of the keystore file and its password.

That example uses a custom store because it is an example of custom SSL. If it used the defaults, it would be an example of default SSL not an example of custom SSL. For many actual applications using the defaults is fine.

Aside: specifying only TLSv1 (meaning 1.0) for protocol is way out of date, and is likely to be considered insecure or at least borderline. It hasn't actually been broken outright like SSLv3 (and long ago SSLv2), because BEAST proved tamer than feared, but TLSv1.1 and 1.2 are now widely implemented and used, and 1.3 hopefully not too far away, so using 1.0 is widely considered substandard and for one example applicable to many people TLSv1.0 for payment-card transactions is prohibited outright as of last weekend.

Sign up to request clarification or add additional context in comments.

4 Comments

Before accepting the answer let me see if I understand it: So we need an SSLContext only if we need to recognize some CA not included in the default truststore file from Java right?
and in that case why is a keystore file added instead of a trustore file? and what is that password?
Yes. That file is a truststore, but is in keystore format; Java uses the same formats (and the same KeyStore class) to contain either 'key+cert-for-me' called a PrivateKeyEntry or 'anchor-cert-for-others' (where most anchors are CAs) called a TrustedCertEntry or any combination; list the file with keytool -list to see which you have. The password is the password (if any) for the file; the commonly used keystore formats (JKS, JCEKS, BKS, PKCS12) all require passwords, although Java allows a keystore to have no password (e.g. Windows-MY, some PKCS11 devices).
PS: the (initial) password for the default cacerts is changeit, which is (AFAICT only) documented near the bottom of the keytool page. But since this is the default you don't normally need to specify it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.