Java™ Secure Socket Extension
Sample Code
README

----------------------------------------------------------------------
CONTENTS
----------------------------------------------------------------------
    - Introduction
    - Sample Keystores and Truststore
    - Code Examples
    - Troubleshooting

----------------------------------------------------------------------
Introduction
----------------------------------------------------------------------
The JSSE sample code provides some simple examples of how
the JSSE can be used to secure communications in the Java™ network
environment. The samples require some familiarity with Java and the
JSSE API.

----------------------------------------------------------------------
Sample Keystores and Truststore
----------------------------------------------------------------------
The JSSE sample code requires keystore and truststore files to 
authenticate the clients and servers. The following steps generate the
certificate stores required by the secure socket connection samples.
If you are running these command-line examples on Windows, then
replace the backslash (\) at the end of each line with a carat (^).

1. Create the keystore for the server, samples/sockets/server/testkeys:

keytool -genkeypair \
  -alias localhost \
  -keystore samples/sockets/server/testkeys \
  -storetype PKCS12 \
  -storepass passphrase \
  -keypass passphrase \
  -keyalg RSA \
  -keysize 2048 \
  -sigalg SHA256withRSA \
  -validity 3650 \
  -dname "CN=localhost, OU=JSSE Samples, O=Demo, L=Toronto, ST=ON, C=CA" \
  -ext "SAN=dns:localhost,ip:127.0.0.1" \
  -ext "EKU=serverAuth"
  
2. Create the keystore for the client, samples/sockets/client/testkeys:

keytool -genkeypair \
  -alias duke \
  -keystore samples/sockets/client/testkeys \
  -storetype PKCS12 \
  -storepass passphrase \
  -keypass passphrase \
  -keyalg RSA \
  -keysize 2048 \
  -sigalg SHA256withRSA \
  -validity 3650 \
  -dname "CN=Duke, OU=JSSE Samples, O=Demo, L=Toronto, ST=ON, C=CA" \
  -ext "EKU=clientAuth"
  
3. Export the server's public certificate to a file:

keytool -exportcert -rfc \
  -alias localhost \
  -keystore samples/sockets/server/testkeys \
  -storepass passphrase \
  -file localhost.cer
  
4. Export the client's public certificate to a file:

keytool -exportcert -rfc \
  -alias duke \
  -keystore samples/sockets/client/testkeys \
  -storepass passphrase \
  -file duke.cer
  
5. Create the truststore, samples/sampletruststore, and import both
certificates:

keytool -importcert -noprompt \
  -alias localhost \
  -keystore samples/sampletruststore \
  -storetype PKCS12 \
  -storepass changeit \
  -file localhost.cer
  
keytool -importcert -noprompt \
  -alias duke \
  -keystore samples/sampletruststore \
  -storetype PKCS12 \
  -storepass changeit \
  -file duke.cer

Specify the location of the truststore and its password through system
properties:

java -Djavax.net.ssl.trustStore=sampletruststore \
  -Djavax.net.ssl.trustStorePassword=changeit
  Application

----------------------------------------------------------------------
Code Examples
----------------------------------------------------------------------
The sample code bundle is broken into several directories, based on
the style of SSL connections.

urls

    URLReader.java

    This example illustrates using a URL to access resources on a
    secure site. By default, this example connects to
    www.oracle.com, but it can be adapted to connect to the
    ClassFileServer below. To do so, the URL will need to be
    modified to point to the correct address. You may also need to
    update the server's certificate or provide a custom
    HostnameVerifier (see HttpsURLConnection) if the hostname in
    the server's certificate doesn't match the URL's hostname.

    SPECIAL NOTES:
        If you are behind a firewall, you may need to set
        the "https.proxyHost" and "https.proxyPort" System
        properties to correctly specify the proxy.

    USAGE:
        java URLReader


    URLReaderWithOptions.java

    This example is very similar to URLReader above, but
    allows you to set the system properties via arguments to the
    main method, rather than as -D options to the java runtime
    environment.

    USAGE:
        java URLReaderWithOptions [-h proxyhost] [-p proxyport] \
            [-k protocolhandlerpkgs] [-c ciphersarray]

        proxyHost = secure proxy server hostname (https.proxyHost)
        proxyPort = secure proxy server port (https.proxyPort)
        protocolhandlerpkgs = a "|" separated list of protocol handlers
            (java.protocol.handler.pkgs)
        ciphersarray = enabled cipher suites as a comma separated list
            (https.cipherSuites)

sockets

    server

    ClassServer.java
    ClassFileServer.java

        This sample demonstrates the implementation of a
        mini-webserver, which can service simple HTTP or HTTPS
        requests (only the GET method is supported).

        By default, the server does not use SSL/TLS. However,
        a command line option enables SSL/TLS.

        Requests must be of the form:

        GET /<filename>

        USAGE:
        java ClassFileServer port docroot [TLS [true]]

            port = the port on which the server resides
            docroot = the root of the local directory hierarchy
            TLS = an optional flag which enables SSL/TLS
            services
            true = an optional flag which requires that clients
            authenticate themselves. This option requires
            that SSL/TLS support be enabled.
            
        NOTE: The ClassFileServer sample expects the keystore for the
        server, testkeys, which contains localhost's credentials,
        to be in the current working directory.
            
        For example, suppose the following:
        * The JSSE sample code is in the directory jssesamples/samples
        * You compiled the source files in the same directory where they reside
        * The file index.html, which the SSLSocketClientWithClientAuth
          sample attempts to read, is in jssesamples/samples
        
        1. Copy jssesamples/samples/sockets/server/testkeys to the
           jssesamples directory.
           
        2. Run ClassFileServer from the jssesamples directory:

        java -cp samples/sockets/server \
          -Djavax.net.ssl.trustStore=samples/sampletruststore \
          -Djavax.net.ssl.trustStorePassword=changeit \
          ClassFileServer 2002 samples TLS true

    client

    SSLSocketClient.java

        This example demonstrates how to use a SSLSocket as a client
        to send a HTTP request and get a response from an HTTPS
        server. By default, this example connects to docs.oracle.com,
        but it can easily be adapted to connect to the ClassFileServer
        above. (Note: The GET request must be slightly modified,
        so that a file is specified.)

        This application assumes the client is not behind a firewall.

        USAGE:
        java SSLSocketClient

    SSLSocketClientWithClientAuth.java

        This example is similar to SSLSocketClient above, but
        this shows how to set up a key manager to do client
        authentication if required by server.

        This application also assumes the client is not behind a
        firewall.

        USAGE:
        java SSLSocketClientWithClientAuth host port requestedfilepath

        NOTE: The SSLSocketClientWithClientAuth expects the keystore
        for the client, testkeys, which contains duke's credentials,
        to be in the current working directory.
        
        For example, suppose the JSSE sample code is in the directory
        jssesamples/samples, and you compiled the source files
        in the same directory where they reside. You can run
        SSLSocketClientWithClientAuth from the
        jssesamples/samples/sockets/client directory as follows:
        
        java -cp . -Djavax.net.debug=all \
          -Djavax.net.ssl.trustStore=../../sampletruststore \
          -Djavax.net.ssl.trustStorePassword=changeit \
          -Djavax.net.ssl.trustStoreType=PKCS12 \
          SSLSocketClientWithClientAuth localhost 2002 /index.html

    SSLSocketClientWithTunneling.java

        This example illustrates how to do proxy Tunneling to access a
        secure web server from behind a firewall.

        The System properties "https.proxyHost" and "https.proxyPort"
        are used to make a socket connection to the proxy host, and
        then the SSLSocket is layered on top of that Socket.

        USAGE:
        java SSLSocketClientWithTunneling

sslengine

    SSLEngineSimpleDemo.java

    This example demonstrates a very simple client/server
    application using SSLEngines. It demonstrates the APIs without
    taking into account I/O or compute issues.

    USAGE:
    java SSLEngineSimpleDemo

----------------------------------------------------------------------
Troubleshooting
----------------------------------------------------------------------
One of the most common problems people have in using JSSE is when the
JSSE receives a certificate that is unknown to the mechanism that
makes trust decisions. If an unknown certificate is received, the
trust mechanism will throw an exception saying that the certificate is
untrusted. Make sure that the correct trust store is being used,
and that the JSSE is installed and configured correctly.

If you are using the "localhost" or "duke" credentials, be sure that
you have correctly specified the location of the sampletruststore
file, otherwise your application will not work. (See
"Sample Key Stores" for more information.)

The SSL debug mechanism can be used to investigate such trust
problems. See the implementation documentation for more information
about this subject.