www.Linux-Support.com

  • Increase font size
  • Default font size
  • Decrease font size
Home

Custom SSL Certificates and HTTPs with Java Clients

Print
Article Index
1. Java and HTTP / HTTPS
2. The Problem
3. The Solution
3.1. Sample Java Code
3.2. Prepare a Key Store
3.3. JVM Parameters
3.4. Starting the JVM

source-java-iconYou are utilizing Java 5 or Java 6 and you want to establish a network connection to a HTTPS server? This task can be tricky if the server side is using a certificate issued by an certificate authority (CA) that is unknown to your Java Virtual Machine (JVM).

This article shows you how to encourage your JVM to talk to server backend systems with custom SSL certificates.

1. Java and HTTP / HTTPS

Java supports to establish connections to servers by talking HTTP and HTTPS by defaut. However, the JVM has registered a set of CAs that are trustworthy. Connections the servers containing certificates signed from CAs that are unknown to your JVM are rejected by throwing a SSLHandshakeException and a SunCertPathBuilderException. You will get error messages like 'PKIX path building failed' and 'unable to find valid certification path to requested target'.

2. The Problem

Java is intended to be a secure environment for applications running in virtual machines. So not anyone is allowed to provide data to your applications by default. There are an number of opportunities to get around this problem. This article will show you an example to end up successfully with this task.

3. The Solution

As usual there are a number of solutions to reach your aims. Here are a number of possible approaches.

  • Extend the default keystore with custom certificates. This step might be difficult if you do not have administrative access permissions at the machines that are running your programs.
  • Extend your program to ignore all certificate failures.
  • Customize your program and utilize a newly created key store.
  • Setup a security manager with a custom rule set.
  • ...
  • Create a key store and tell your JVM to utilize it at start time.

From all these approaches the latter one is the solution that we will try to configure in this article!

3.1. Sample Java Code

This is a code example to open a HTTP(s) connection. Without any additional code or configurations this application will fail, when connection to an unsecure server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
 
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
 
 
/** Connect to a HTTP or HTTPS server (runs with Java 5 and Java 6).
 * @author marioscondo
 *
 * Copyright 2010, Linux-Support.com
 */
public class HttpsTest {
 
/**
  * @param args provide an optional url
  */
public static void main(String[] args) {
// main method - this is the entry point for running this application
HttpsTest app = new HttpsTest();
try {
// fetch a url from command line or use a default one
String url = "https://www.linux-support.com:443/";
if (args.length > 0) {
url = args[0];
}
 
System.out.println("connecting to: " + url);
 
// fetch remote data
app.doit(url);
 
} catch (Exception e) {
e.printStackTrace();
}
}
 
// connect to the server
void doit(String url_str) throws Exception {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL(url_str);
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
 
String string = null;
System.out.println("connection was successful.");
System.out.println("received data:");
while ((string = bufferedreader.readLine()) != null) {
System.out.println("Received " + string);
}
 
}
}
 

This is a very simple connection tester. If available, it takes the first command line argument and tries to connect to this url. If no parameter is available a default server will be utilized (www.linux-support.com via HTTPS). The method doit(...) is opening the network connection and is printing out all the data that has been received. If an error occures (like there is an untrusted server at the other end of the network connection) an exception will be thrown.

3.2. Prepare a Key Store

Now we want to create a key store to be provided to your JVM. It may contain any number of certificates. In this example we will add the certificate of the CA, that did sign the certificate of our target HTTPS server. This will result in successful network connections for all requests to servers this CA did sign. So we do not need to import all the certificates of each and every HTTPS service we want to talk to.

# create a key store and import the certificate of a CA
$ keytool -import -storepass passwd -keystore mykeystore -alias lsca -file cacert.crt
 

This single line is performing all the following steps at once:

  • create a key store named mykeystore
  • set the password passwd for the keystore (it is required to secure and access data within the key store)
  • import the certificate cacert.crt into the key store
  • set the alias lsca for the imported certificate

If you are asking yourself, where to get the CA certificate from, we have got a reassuring answer to you. Each CA is publishing its certificate at its public website. If you are interested in connecting to the preconfigured default Url (see above) you may download the CA certificate at the following location: http://www.linux-support.com/cert/cacert-premium.crt

3.3. JVM Parameters

These are the parameters recognized by the JVM to start with an additional key store and/or trust store.

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=gridserver.keystore
-Djavax.net.debug=ssl # very verbose debug
-Djavax.net.ssl.keyStorePassword=$PASS
-Djavax.net.ssl.trustStorePassword=$PASS
 

Don't worry. For our example we just need two parameters from that list.

3.4. Starting the JVM

Now we are ready to start the application. After compiling the sample application and creating the key store you might key-in the following command line to connect to the preconfigured default url. In the next example we assume that your application is packaged within the file test-https.jar.

# run the application
$ java -Djavax.net.ssl.keyStorePassword=passwd \
-Djavax.net.ssl.trustStore=mykeystore \
-jar test-https.jar
 
# run the application from an intranet by utilizing
# a proxy server
$ java -Djavax.net.ssl.keyStorePassword=passwd \
-Djavax.net.ssl.trustStore=mykeystore \
-Dhttp.proxyHost=wwwproxy.yournet.corp \
-Dhttp.proxyPort=8080 \
-Dhttps.proxyHost=wwwproxy.yournet.corp \
-Dhttps.proxyPort=8080 \
-jar test-https.jar
 

Have a lot of fun with your new extended SSL client!

Related articles:

Last Updated on Wednesday, 25 August 2010 11:34