Chapter 7. TLS

## Chapter 7. TLS

### TLS Support (a.k.a. SSL)

### Blaine Simpson

HSQLDB Development Group
`<blaine.simpson@admc.com>`

$Date: 2005/11/06 20:03:37 $

The instructions in this document are liable to change at any time. In particular, we will be changing the method to supply the server-side certificate password.

## Requirements

Hsqldb TLS Support Requirements

- Sun Java 2.x and up. (This is probably possible with IBM's Java, but I don't think anybody has attempted to run HSQLDB with TLS under IBM's Java, and I'm sure that nobody in the HSQLDB Development Group has documented how to set up the environment).

- If Java 2.x or 3.x, then you will need need to install JSSE. Your server and/or client will start up much slower than that of Java 4.x users. Client-side users will not be able to use the https: JDBC protocol (because the https protocol handler is not implemented in 2.x/3.x Java JSSE; if there is demand, we could work around this).

- A JKS keystore containing a private key, in order to run a server.

- If you are running the server side, then you'll need to run a HSQLDB Server or WebServer. It doesn't matter if the underlying database instances are new, and it doesn't matter if you are making a new Server configuration or encrypting an existing Server configuration. (You can turn encryption on and off at will).

- You need a HSQLDB jar file that was built with JSSE present. If you got your HSQLDB 1.7.2 distribution from us, you are all set, because we build with Java 1.4 (which contains JSSE). If you build your own jar file with Java 1.3, make sure to install JSSE first.

## Encrypting your JDBC connection

At this time, only 1-way, server-cert encryption is tested.

### Client-Side

Just use one of the following protocol prefixes.

Hsqldb TLS URL Prefixes

- `jdbc:hsqldb:hsqls://`

- `jdbc:hsqldb:https://`

At this time, the latter will only work for clients running with Java 1.4.

If the server you wish to connect to is using a certificate approved by your default trust keystores, then there is nothing else to do. If not, then you need to tell Java to "trust" the server cert. (It's a slight over-simplification to say that if the server certificate was purchased, then you are all set; if somebody "signed their own" certificate by self-signing or using a private ca certificate, then you need to set up trust).

First, you need to obtain the cert (only the "public" part of it). Since this cert is passed to all clients, you could obtain it by writing a java client that dumps it to file, or perhaps by using openssl s_client. Since in most cases, if you want to trust a non-commercial cert, you probably have access to the server keystore, I'll show an example of how to get what you need from the server-side JKS keystore.

You may already have an X509 cert for your server. If you have a server keystore, then you can generate a X509 cert like this.

Example 7.1. Exporting certificate from the server's keystore

        keytool -export -keystore server.store -alias existing_alias -file server.cer

In this example, `server.cer` is the X509 certificate that you need for the next step.

Now, you need to add this cert to one of the system trust keystores or to a keystore of your own. See the Customizing Stores section in JSSERefGuide.html to see where your system trust keystores are. You can put private keystores anywhere you want to. The following command will add the cert to an existing keystore, or create a new keystore if `client.store` doesn't exist.

Example 7.2. Adding a certificate to the client keystore

    keytool -import -trustcacerts -keystore trust.store -alias new_alias -file server.cer

If you are making a new keystore, you probably want to start with a copy of your system default keystore which you can find somewhere under your JAVA_HOME directory (typically jre/lib/security/cacerts for a JDK, but I forget exactly where it is for a JRE).

Unless your OS can't stop other people from writing to your files, you probably do not want to set a password on the trust keystore.

If you added the cert to a system trust store, then you are finished. Otherwise you will need to specify your custom trust keystore to your client program. The generic way to set the trust keystore is to set the sytem property `javax.net.ssl.trustStore` every time that you run your client program. For example

Example 7.3. Specifying your own trust store to a JDBC client

        java -Djavax.net.ssl.trustStore=/home/blaine/trust.store -jar /path/to/hsqldb.jar dest-urlid

This example runs the program SqlTool. SqlTool has built-in TLS support, however, so, for SqlTool you can set `truststore` on a per-urlid basis in the SqlTool configuration file.

N.b. The hostname in your database URL must match the Common Name of the server's certificate exactly. That means that if a site certificate is `admc.com`, you can not use `jdbc:hsqldb:hsqls://localhost` or `jdbc:hsqldb:hsqls://www.admc.com:1100` to connect to it.

If you want more details on anything, see JSSERefGuide.html on Sun's site, or in the subdirectory `docs/guide/security/jsse` of your Java SE docs.

### Server-Side

Get yourself a JKS keystore containing a private key. Then set the system property javax.net.ssl.keyStore to the path to that file, and `javax.net.ssl.keyStorePassword` to the password of the keystore (and to the private key-- they have to be the same).

Example 7.4. Running an Hsqldb server with TLS encryption

        java -Djavax.net.ssl.keyStorePassword=secret  \
            -Djavax.net.ssl.keyStore=/usr/hsqldb/db/db3/server.store  \
            -cp /path/to/hsqldb.jar org.hsqldb.Server

(This is a single command that I have broken into 2 lines using my shell's \ line-continuation feature. In this example, I'm using a server.properties file so that I don't need to give arguments to specify database instances or the server endpoint).

### Caution

Specifying a password on the command-line is definitely not secure. It's really only appropriate when untrusted users do not have any access to your computer.

If there is any user demand, we will have a more secure way to supply the password before long.

## JSSE

If you are running Java 4.x, then you are all set. Java 1.x users, you are on your own (Sun does not provide a JSSE that will work with 1.x). Java 2.x and 3.x users continue...

Go to http://java.sun.com/products/jsse/index-103.html. If you agree to the terms and meet the requirements, download the domestic or global JSSE software. All you need from the software distro is the three jar files. If you have a JDK installation, then move the 3 jar files into the directory `$JAVA_HOME/jre/lib/ext`. If you have a JRE installation, then move the 3 jar files into the directory `$JAVA_HOME/lib/ext`.

Pretty painless.

## Making a Private-key Keystore

There are two main ways to do this. Either you can use a certificate signed by a certificate authority, or you can make your own. One thing that you need to know in both cases is, the Common Name of the cert has to be the exact hostname that JDBC clients will use in their database URL.

### CA-Signed Cert

I'm not going to tell you how to get a CA-signed SSL certificate. That is well documented at many other places.

Assuming that you have a standard pem-style private key certificate, here's how you can use openssl and the program `DERImport` to get it into a JKS keystore.

Because I have spent a lot of time on this document already, I am just giving you an example.

Example 7.5. Getting a pem-style private key into a JKS keystore

    openssl pkcs8 -topk8 -outform DER -in Xpvk.pem -inform PEM -out Xpvk.pk8 -nocrypt

    openssl x509 -in Xcert.pem -out Xcert.der -outform DER

    java DERImport new.keystore NEWALIAS Xpvk.pk8 Xcert.der

### Important

Make sure to set the password of the key exactly the same as the password for the keystore!

You need the program `DERImport.class` of course. Do some internet searches to find `DERImport.java` or `DERImport.class` and download it.

If DERImport has become difficult to obtain, I can write a program to do the same thing-- just let me know.

### Non-CA-Signed Cert

Run `man keytool` or see the Creating a Keystore section of JSSERefGuide.html.

## Automatic Server or WebServer startup on UNIX

If you are on UNIX and want to automatically start and stop a Server or WebServer running with encryption, follow the instructions in the UNIX Quick Start chapter, and remember to make the init script configuration file readable only to root and to set the variables `TLS_PASSWORD` and `TLS_KEYSTORE`.

If you are using a private server certificate, make sure to also set the trust store filepath as shown in the sample init script configuration file.

The cautionary warning above still applies. The password will be visible to any minimally competent local UNIX user who wants to see it.

Chapter 6. Text Tables |  | Chapter 8. SqlTool