print Print
Logo: Stiftung Secure Information and Communication Technologies SIC Stiftung Secure Information and Communication Technologies SIC

isasilk and https

This document explains how to secure HTTPS traffic with SSL/TLS using iSaSiLk.
We give a quick rundown of the demo and explain how the API can be used.

Basically what the code allows you to do is to use HTTPS URLs with the
java.net.URL class, open connections to
perform requests and read responses, just like standard HTTP URLs
are supported in the JDK.

Note: This document does not give a complete description
of all features of Java™ URLs and HttpURLConnections,
please refer to the iSaSiLk and JDK JavaDoc files or additional information.

General

HTTPS is nothing more than the HTTP protocol over SSL/TLS rather
than over plain TCP. As such it would be quite easy to add HTTPS to any
HTTP implementation given the necessary hooks for the transport are
provided or the source is available.

Unfortunately this is not the case for the HTTP code that comes with the JDK.
As developing a stable and fairly complete implementation of HTTP/1.1 would
be a serious undertaking and reinventing the wheel is something we prefer to
avoid, we decided not to do yet another HTTP implementation and to use the
W3C's HTTP code that comes with their Jigsaw Web server instead (see license
notice).

Essentially what we did was to take the Jigsaw source (current version 2.2.6), remove a
lot of classes which are not required for HTTP URL support, and modify
a few classes to allow for HTTPS. We provide the result as the JAR
file w3c_http.jar which has to be used in addition to
the iSaSiLk iaik_ssl.jar file for HTTPS support.

As a sidenote we would also like to point at that there is at least one third
party HTTP implementation that can be used with iSaSiLk to provide
HTTPS support. It is called HTTPClient, is free under a LGPL license and
available online.
Please note that this is a pointer to a possible alternate solution
only and not an endorsement of this software. As a matter of fact we have
never evaluated it and of course cannot answer any support questions about it.

Using HTTPS

This section explains how to actually use HTTPS by describing the demo
supplied with the iSaSiLk distribution. Its source is located in
HttpsDemo.java example and it is available in
compiled form in the iaik_ssl_demo.jar file.

Running the Demo

To try out the demo do the following (assuming you are using the IAIK JCE
as your cryptographic provider and a JDK version on a Windows platform):

set CLASSPATH=%CLASSPATH%;.;lib\iaik_ssl.jar;lib\w3c_http.jar;lib\iaik_jce_full.jar
java demo.https.HttpsDemo https://jce.iaik.tugraz.at/

Note that the HTTPS code requires w3c_http.jar in addition to iaik_ssl.jar.
The demo then will open a HTTPS connection to https://jce.iaik.tugraz.at/, display
some status information and then print the downloaded HTML page. You can select
a different server by passing its URL as argument to the demo.

The Demo Code

As shown in the demo using HTTPS is very simple. Summarized, the steps to
follow are:

  1. Setup your environment for HTTPS.
    Make sure you have w3c_http.jar in your CLASSPATH
    in addition to iaik_ssl.jar and your cryptographic code.
    In your program register HTTPS URLs so that they can be used,
    for more information see the next section.
  2. Setup the SSL code so that it is ready to go, i.e.
    add your cryptographic provider and set your SecurityProvider if necessary.
    Then set the SSL parameters you want to use in an SSLContext. Either
    set it as the default SSL context using the static method
    HttpsURLConnection.setDefaultSSLContext() or set it
    dynamically on your URLConnection using setSSLContext()
  3. Create HTTPS URLs and calls openConnection() on them.
    A HttpsURLConnection object is returned. You can perform
    all standard java.net.HttpURLConnection operations on it
    and additionally call getSSLSocket() to get SSL parameters
    directly from the socket. Note: do not forget to set
    your SSLContext on this object unless you set a static default.

Registering HTTPS URLs

The HTTPS protocol has to be registered with the java.net
APIs before it can be used. There are several options:

  • Set the system property java.protocol.handler.pkgs.
    Use for example

    System.getProperties().put("java.protocol.handler.pkgs", "iaik.protocol");

    This property can contain a list of packages used to search for
    protocol handlers. For more information see the JDK documentation for
    the java.net.URL class. Note that this will not work if a factory is installed,

  • Set the factor for URLStreamHandler. Use code like

    java.net.URL.setURLStreamHandlerFactory(new iaik.protocol.https.HttpsURLStreamHandlerFactory());

    For some reason the JDK code allows the factory to be set only once.
    That means if you environment already has a factory installed for some
    reason (as usually the case with Applets or Servlets) this code cannot be
    used either. In that case you can only check the installed factory if
    it allows other protocols to be added in some way.

  • If you are using JDK 1.2 or later you can specify the handler dynamically
    when creating an URL object.

    URL u = new URL(null, "https://...", new iaik.protocol.https.Handler());

    Note that all your HTTPS URLs have to be created in this way. Also note
    that you need not create a new Handler object each time, you can use the
    same for all URLs.

HTTPS Without Registering URLs

For cases where the above approaches cannot be used we provide a limited
workaround. Because HTTPS URLs cannot even be created if no appropriate
protocol handler is installed they cannot be used in this case but it is
still possible to speak HTTPS via the provided implementation. To do this
create a HTTP (!) URL specifying the target host and port and pass it
directly to the constructor of the class iaik.protocol.https.HttpsURLConnection.
For example, use code like this:

URL u = new URL("https://jce.iaik.tugraz.at:443/");
URLConnection connection = new HttpsURLConnection(u);
InputStream in = connection.getInputStream();

Note that you must specify a destination port in this case,
you cannot use the default port (80 would be used as for HTTP). Also note that
this is a limited workaround only, we recommend using it only if the other options
are not available. This problem is due to a limitation in the JDK software
and not in ours.

Using the POST Method

HTTP defines a number of request methods. Most often used is the GET
method, which is appropriate to retrieve data from the server.
Another request method is POST, which is most usefull to send large
amounts of data to the server. iSaSiLk supports both.

However, in difference to the original JDK HTTP implementation the POST
method is not automatically chosen if you enable both input and output
for the connection. To use the POST method use code like this:

HttpsURLConnection con = (HttpsURLConnection)url.openConnection();

// setup SSL-configuration
con.setSSLContext(context);

con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);

OutputStream out = con.getOutputStream();
out.write("foobar".getBytes());
out.flush();

InputStream in = con.getInputStream();

Important: Please note the order in which the methods are executed and also that
all data must be written before calling getInputStream().

Connecting via a Proxy

For connecting via a proxy the host name and port number of the proxy have to
be set as System properties using "https.proxyHost" and
"https.proxyPort" as key words, e.g.:

String proxyHost = ...;
int proxyPort = ...;
 System.setProperty("https.proxyHost", proxyHost);
System.setProperty("https.proxyPort", proxyPort);
...

If the proxy requires a user to authenticate him/herself by username and
password, this either may be done in the common way by setting a request
property on the HttpsURLConnection object or by specifying user name and
password via System properties.
When setting proxy user name and password via request property you have to
use "Https-Proxy-Authorization" as key. The value consists of
authentication scheme ("Basic") and username/password encoding (base64) as
accustomed from normal (proxy) authentication, e.g.:

String authString = "userid:password";
String authMsg = "Basic " + base64encode(authString.getBytes());
URL url = new URL("https://...");
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
...
con.setRequestProperty("Https-Proxy-Authorization", authMsg);

Please ensure to use "Https-Proxy-Authorization" as key only when
connecting through a authentication requesting HTTPS proxy! Do not use another
key like "Proxy-Authorization" or
"Authorization". It would not be recognized and so may travel
to the target server. You may test the behaviour of your proxy by connecting
through it to an iSaSiLk server to see what is actually send to the server.

When setting HTTPS proxy user and password via System properties (may not be
the recommended way except you are sure that no one else may have access to your
client machine), use "https.proxyUser" and
"https.proxyPassword" as keys:

String httpsProxyUser = ...;
String httpsProxyPassword =...;
System.setProperty("https.proxyUser", httpsProxyUser);
System.setProperty("https.proxyPassword", httpsProxyPassword);

Moreover, it is possible to specify a list of hosts for which the library should
not use a proxy. This can be done using the https.nonProxyHosts
property. The use is similar to the http.nonProxyHosts property.
The value of this property is a '|' separated list of host names. The '*' as wildcard character
is allowed as first character of a name in the list. For example:

System.setProperty("https.nonProxyHosts", "*.tugraz.at|www.iaik.at");

For a host that matches any of the names in this list, the library will establish
the connection directly without using the proxy.

Notes

  • The HTTP implementation is not ours but the W3C's. We can only
    provide limited support for not SSL specific problems.
  • The W3C library provides a whole set of additional features
    and an entire alternate API. However, those have not been tested
    AT ALL and should NOT be used.
    The only functionality we support
    is the one described above, i.e. creation of HTTPS URLs and calling
    openConnection() on them.
  • No operations other than SSL status query calls should be
    executed on the socket returned by getSSLSocket().
    For example, you can use it to determine the active SSL ciphersuite
    or to obtain the server certificates, but do not access its
    streams, etc.
  • Because the HTTP library employs persistent connections that
    are possibly used for multiple HTTPS requests, changes to an
    SSLContext may not be immediately reflected in successive connections
    if they are to a server with which a HTTPS connection was already
    previously established! It is assumed that this will generally
    not be a problem because the SSL preferences only rarely ever
    need to be changed in the middle of a connection.
  • HTTPS connections are automatically established through
    a HTTP proxy if the respective settings have been made in the
    Java™ environment. SOCKS proxies are supported by the original
    java.net.Socket class anyway.
    See iaik.security.ssl.Utils.proxyConnect()
    for details.
 

print Print