# Using Jetty and JSSE

This is an overview of how to use Jetty with JSSE as an SSL implementation. The 1.0 release of JSSE contains both a frame work for third party providers and a reference implementation. These instructions detail how to use the reference implementation and have been tested against keys generated from the sun keytool utility and 024 and 2048 bit RSA keys from openssl

Note that while Jetty2 compiles and runs under Java 1.1.x, SSL and JSSE support require at least Java 1.2.x.

There are three steps.

1. Get the private key and cert.
2. Load the private key and cert into a Sun JKS keystore.
3. Configure Jetty to use JSSE and the keystore.

This document also contains an environment description with version numbers and a list of outstanding issues.

## Step 1: Get the private key and cert.

If you already have a key and cert then skip to step two.

Sun Key/Certificate Pair
In order to generate the certificate with the reference implementation you need to install the JSEE as a security provider for JDK. You can do this by editing $JDK12/jre/lib/security/java.security and adding the following lines:

          security.provider.2=com.sun.net.ssl.internal.ssl.Provider

This is assuming that JSSE is the only additional provider you want installed. Note that all Jetty Jsse classes manually install this provider as needed, so it may be worthwhile removing this line after the certificate has been generated, as it can interfer with other providers (see loading OpenSSL keypair below).

The certificate can be generated and loaded with the keytool utility with a command like:

      keytool -genkey -keyalg RSA -storepass testpasswd -keypass testpasswd

OpenSSL Key/Certificate Pair
The procedure to get a key and certificate for use with OpenSSL is described in Thawte's Apache SSL Key and CSR Generation Instructions.

Here is a log of me following a simplified version of those instructions.

    $ mkdir keytest
    $ cd keytest
    $ openssl genrsa -des3 -rand /var/log/wtmp:/var/log/boot.log:/var/tmp/lastlog:/var/log/messages 1024 > bee.hive.net.key
    235890 semi-random bytes loaded
    Generating RSA private key, 1024 bit long modulus
    ...............................++++++
    ...............................................++++++
    e is 65537 (0x10001)
    Enter PEM pass phrase:
    Verifying password - Enter PEM pass phrase:
    $ openssl req -new -key bee.hive.net.key > bee.hive.net.csr
    Using configuration from /usr/share/ssl/openssl.cnf
    Enter PEM pass phrase:
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:
    State or Province Name (full name) [Some-State]:
    Locality Name (eg, city) []:
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:
    Organizational Unit Name (eg, section) []:
    Common Name (eg, YOUR name) []:bee.hive.net
    Email Address []:postmaster@bee.hive.net

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:challenge
    An optional company name []:

    $ cat bee.hive.net.csr
    -----BEGIN CERTIFICATE REQUEST-----
    MIIB3zCCAUgCAQAwgYQxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRl
    MSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTATBgNVBAMTDGJl
    ZS5oaXZlLm5ldDEmMCQGCSqGSIb3DQEJARYXcG9zdG1hc3RlckBiZWUuaGl2ZS5u
    ZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKE3ChwybfDMtDBm54mWKpHQ
    wQ5Dla0JC4SSlP4xhq6J2j5MpXWM1CgpqJWwYqr4tEFrD0kMOUZDby6R5nC3iuSt
    bIlWx6xztzKI6Jngg8wM2FRwlMbZIfUvmgJ6abvknE0VRSEm4RRCQehnk7FCz1aa
    W8esCm9r+9vXvULhGXAhAgMBAAGgGjAYBgkqhkiG9w0BCQcxCxMJY2hhbGxlbmdl
    MA0GCSqGSIb3DQEBBAUAA4GBAHtvSlMrKaiP5Yfn/WgbaLUbEXlf/9DX2EIWVI4p
    QTpHApt/DQLdYNXs2stzXNOfZNGtmhATvvfOOLTZYxqn3l/qYeiAJMDU2q2yc7YU
    i3yvGO2HVbRlB2vbtdFG6CzzaA/nszi+ZXQ07ltOUX7B0WMZLyHt/lUFMH3Rc7qF
    CRw2
    -----END CERTIFICATE REQUEST-----

Use a browser to paste the above into the a form for submission to the CA. I used Thawte's Test Certificate CA. Place the result into a suitably named file as follows:

    $ cat > bee.hive.net.crt
    -----BEGIN CERTIFICATE-----
    MIICqjCCAhOgAwIBAgIDPLWSMA0GCSqGSIb3DQEBBAUAMIGHMQswCQYDVQQGEwJa
    QTEiMCAGA1UECBMZRk9SIFRFU1RJTkcgUFVSUE9TRVMgT05MWTEdMBsGA1UEChMU
    VGhhd3RlIENlcnRpZmljYXRpb24xFzAVBgNVBAsTDlRFU1QgVEVTVCBURVNUMRww
    GgYDVQQDExNUaGF3dGUgVGVzdCBDQSBSb290MB4XDTAwMDgxMjEwMzYxMloXDTAx
    MDgxMjEwMzYxMlowgYQxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRl
    MSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTATBgNVBAMTDGJl
    ZS5oaXZlLm5ldDEmMCQGCSqGSIb3DQEJARYXcG9zdG1hc3RlckBiZWUuaGl2ZS5u
    ZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKE3ChwybfDMtDBm54mWKpHQ
    wQ5Dla0JC4SSlP4xhq6J2j5MpXWM1CgpqJWwYqr4tEFrD0kMOUZDby6R5nC3iuSt
    bIlWx6xztzKI6Jngg8wM2FRwlMbZIfUvmgJ6abvknE0VRSEm4RRCQehnk7FCz1aa
    W8esCm9r+9vXvULhGXAhAgMBAAGjJTAjMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwG
    A1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEEBQADgYEAhSvgL8nliB29TcOFakQ2i5kq
    VMwVaxWSFBv2oyxW4/p1/7IMUYBTjIDx0wurkbY9I+iJ2rVfLKYtqmU/94oRQnkB
    FrTXTweQPhJSdjvSaZj3QAQBwca6gYcy3mrGCiOHHe/rkN+Yo0FnDyutqmsqs7oB
    eHL4df28CBXV6tva77g=
    -----END CERTIFICATE-----

## Step 2: Load the private key and cert into a Sun JKS keystore.

If a sun provider key/certificate pair was generated, then they are already loaded into the JKS keystore and this step can be skipped.

During this step you will be doing a few exposed things from a security point of view, so only do this in a secure directory on a secure machine. Remember to clean up properly.

Crypto Provider
The JSSE provider is not able to handle openSSL key pairs, so another provider is required. Get your hands on a copy of the Bouncy Castle Crypto Package from The Legion of the Bouncy Castle. Other JCE 1.2 providers may work too but at the moment this is the one that this is tested against. You will only need it for the key loading stage so install it on your safe machine somewhere.

To perform these step, you do not need to have any providers registered in the JRE java.security file. In fact having the JSSE reference provider registered can cause errors in the following step. To use the bouncy castle provider, their classes directory must be in your classpath, for example:

      export CLASSPATH=$CLASSPATH:/usr/local/java/bouncycastle/jce-jdk12-10b3/classes

You can test the bouncy castle installation by running the following test harnesses:

      java org.bouncycastle.crypto.test.RegressionTest
      java org.bouncycastle.jce.provider.test.RegressionTest

Extracting your Private Key
Firstly you will need to decrypt the private key. Do this using openssl like this:

    $ openssl rsa -in bee.hive.net.key -out bee.hive.net.clearkey -outform DER
    read RSA key
    Enter PEM pass phrase:
    writing RSA key

If this fails, check that the sun security provider is not registered in the java.security file. It only needs to be registered their if you are generating your keys with sun's keytool. Jetty registers the provider on an as need be basis.

REMEMBER TO DELETE YOU CLEAR KEY WHEN YOU COMPLETE THE NEXT STEP

Loading Private Key and Certificate into the keystore
Next, load the key and the cert into a JKS keystore. The class com.mortbay.Util.KeyPairTool is used to load the keys into the keystore. It has the following arguments:

    $ java com.mortbay.Util.KeyPairTool
    Tool to insert a private key/certificate pair into a keystore.
    Parameters:
     -key        FILENAME, location of private key [MANDATORY]
     -cert       FILENAME, location of certificate [MANDATORY]
     -keystore   FILENAME, location of keystore,   [~/.keystore]
     -storetype  STRING,   name/type of keystore,  [jks]
     -alias      NAME,     alias used to store key [mykey]
     -provider   NAME,     name of provider class  [org.bouncycastle.jce.provider.BouncyCastleProvider]

    The keystore and key passwords will be prompted for or can be
    set with the following JVM system properties:
      jetty.ssl.password
      jetty.ssl.keypassword

If passwords are not provided as properties, they are prompted for. While they still appear on the screen, this is a much safer option as they do not get saved in shell histories or process listings.

    $ /bin/sh
    $ java com.mortbay.Util.KeyPairTool -key bee.hive.net.clearkey -cert bee.hive.net.crt -storepass testpasswd -keystore mykeystore
    Loaded the private key...
    Loaded the public key...
    Will create keystore: keypair.keystore
    Keys have been written to keystore

Remember to clean up! a simple way to do this without going to overboard is:

    $ man man > bee.hive.net.clearkey
    $ cat /var/log/messages | compress > bee.hive.net.clearkey
    $ man ls > bee.hive.net.clearkey
    $ rm bee.hive.net.clearkey

You now have a keystore with your keypair stashed away in it. If you ignored the previous step, you also have your private key in the clear in your file system - SO CLEAN UP! This is your last warning.

You can use the jdk-1.2 keytool to manipulate the key/cert now that it is in there. You can use it to change the password for instance.

    $ keytool -storepasswd
    Enter keystore password:  testpasswd
    New keystore password:  newpasswd
    Re-enter new keystore password:  newpasswd

    keytool -list
    Enter keystore password:  newpasswd

    Keystore type: jks
    Keystore provider: SUN

    Your keystore contains 1 entry:

    mykey, Sat Aug 12 21:11:19 GMT+10:00 2000, keyEntry,
    Certificate fingerprint (MD5): 1A:DA:C0:35:F0:A3:EC:AD:AB:D8:5F:48:78:A0:CB:90
    $

## Step 3: Configure Jetty to use JSSE and the keystore.

Assuming you already have a functioning Jetty2 Server:

Add the SunJsseListener alongside the HttpListeners, e.g. you could change lines that look like:

    main.LISTENER.all.CLASS : com.mortbay.HTTP.HttpListener
    main.LISTENER.all.ADDRS : 0.0.0.0:8080;127.0.0.1:8888

To:

    main.LISTENER.http.CLASS  : com.mortbay.HTTP.HttpListener
    main.LISTENER.http.ADDRS  : 0.0.0.0:8080;127.0.0.1:8888
    main.LISTENER.https.CLASS : com.mortbay.HTTP.SunJsseListener
    main.LISTENER.https.ADDRS : 0.0.0.0:8443

Remember that the default port for https is 443 not 80, so change 80 to 443 if you want to be able to use URL's without explicit port numbers. For a production site it normally makes sense to have a HttpListener on port 80 and a SunJsseListener on port 443.

Choose a private directory with restricted access to keep your keystore in. Even though it has a password on it, the password may be configured into the runtime environment so is vulnerable to theft.

Change the way you start Jetty to:

- Include all three JSSE provided jar files in the classpath: jsse.jar, jnet.jar & jcert.jar. Remember you no longer need bouncycastle in you classpath.
- Provide the path to the keystore file as the jetty.ssl.keystore property
- Provide the keystore and key passwords, either as the jetty.ssl.password and jetty.ssl.keypassword properties or typed at a prompt.

For example:

    java -Djetty.ssl.keystore=/home/jetty/keystore  com.mortbay.Jetty.Demo

    jetty.ssl.password : testpasswd
    jetty.ssl.keypassword : testpasswd

You may then access the SSL port with a URL like: https://yourhost:8443/Dump If you get an javax.net.ssl.SSLException, check that you have remembered the s in https.

Password Issues
The passwords can also be set on the command line as properties, but remember that putting your password on the command line is a security risk.

If jetty is given a password that begins with "EXEC:", then the rest of the password is treated as a command and run with java.lang.Runtime.exec. The password name (eg. jetty.ssl.password) is written to the input of the command and a line of output is read from the command and used as the password.

If jetty is given a password that begins with "OBF:" it is treated as an obfiscated password. Passwords can be obfiscated by running com.mortbay.Util.Password as a main class.

While these mechanism just exports the security problem for jetty, it does allow customized security arrangements to be configured.

# Outstanding Issues.

The following issues are outstanding:

- Reading passwords from prompts should turn echo off.
- Better recommendations for keystore location and permissions.
- Jetty is not yet ready to insist on client certificates.

# Environment and version information.

The environment this procedure was developed in was:

- Red Hat Linux 6.2 x86 with openssl-0.9.5a-2.i386.rpm installed
- Solaris 2.5.7 with OpenSSL 0.9.4 09 Aug 1999
- Bouncy Castle Crypto Library, Release 1.0 Beta 3
- Jetty-2.4.6
- Sun JavaTM Secure Socket Extension (JSSE) 1.0.1 - Globally Exportable release (Non domestic US version)

Written by Brett Sealey. 13th August 2000.
Updated by Greg Wilkins. 14th August 2000.

I told you to clean up your private key - do it NOW!