import java.net.*; import javax.net.ssl.*; import java.util.*; import java.io.*; /** * This class is a JSSE client that talks to a server over an SSL * connection. Once a connection is made, the client sends a "message" * (defined as a stream terminated by ) to the server, and reads back * the response which is a message sent back by the server. *

The code to perform the SSL stuff is all in "main" - the use of other * methods is limited just to displaying information, so that you should * only need to read the "main" code to see what order things are done. *

Built using JDK1.4 and tested on Windows 2000 * @author Nick Hudson * @version 1.0 */ public class ExampleSSLClient { static Object syncObject = new Object(); /** * Report a message to System.out * @param doTrace true if you want the message to appear, false otherwise * @param message the message to be sent to System.out */ public static void trace(boolean doTrace, String message) { if (doTrace) { synchronized(syncObject) { System.out.println(message); } } } /** * Display usage information */ public static void usage() { trace(true,"\nUsage: java ExampleSSLClient " + " [trace]"); trace(true," server : the server to talk to"); trace(true," port : port number to use"); trace(true," ciphers : types of cipher suites to propose :-"); trace(true," 'c' : suites that use server-cert"); trace(true," 'a' : anonymous (no server-cert)"); trace(true," protocol : '1' or '3' where :-"); trace(true," '1' means TLSv1"); trace(true," '3' means SSLv3"); trace(true," trace : (optional) tracing to enable:-"); trace(true," 'j' : turn on JSSE debug tracing"); trace(true," 't' : turn on program tracing"); } /** * This method looks at the run-time environment in an attempt to check * if things may need setting up for JSSE to work properly. It reports * any areas of concern but does not abort. */ public static void checkEnvironment() { // Check whether they've specified a trustStore. If they haven't, then // JSSE looks for files jssecacerts or cacerts as specified in the // JSSE Reference Guide String trustStoreName = System.getProperty("javax.net.ssl.trustStore"); if (trustStoreName == null) { // Tell them how to set it trace(true, "\nYou have not specified a truststore, which means that JSSE will look in"); trace(true, "default locations (see JSSE Reference Guide) to validate any certificates"); trace(true, "offered by the server. To specify a truststore, use"); trace(true, "use e.g. :\n"); trace(true, " java -Djavax.net.ssl.trustStore=\"\" ...\n"); } } /** * Display various information out of a HandshakeCompletedEvent object. * @param event HandshakeCompletedEvent object. */ public static void showHandshakeInfo(HandshakeCompletedEvent event) { // This method may be called from a separate thread, so all of // the output here in a synchronized block to make sure it doesn't // get interspersed with other messages. synchronized(syncObject) { trace(true,"Negotiated cipher suite " + event.getCipherSuite()); java.security.cert.Certificate lc[] = event.getLocalCertificates(); if (lc != null) { trace(true,"" + lc.length + " local certificates used :"); for (int i=0; i 4) { String traceOptions = args[4].toLowerCase(); isTracing = (traceOptions.indexOf("t") != -1); if (traceOptions.indexOf("j") != -1) { // Enable JSSE tracing trace(isTracing, "Enabling JSSE debug tracing"); System.setProperty("javax.net.debug","ssl"); } } } catch (Exception e) { trace(true,e.toString()); // They invoked the program with invalid arguments usage(); return; } checkEnvironment(); SSLSocketFactory sf = null; SSLSocket socket = null; try { trace(true,"Configuring SSLSocketFactory, please wait..."); sf = (SSLSocketFactory)SSLSocketFactory.getDefault(); trace(isTracing,"Creating new client Socket"); socket = (SSLSocket)sf.createSocket(serverAddr,portNumber); if (isTracing) { socket.addHandshakeCompletedListener(new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent e) { trace(true,"SSL handshake completed : "); showHandshakeInfo(e); } }); } // Look at each of the supported cipher suites, and build a list // of those that we want to use, based on the user's requirements String[] supportedSuites = socket.getSupportedCipherSuites(); HashSet set = new HashSet(); trace(isTracing,"Supported cipher suites are:"); for (int i=0; i" + message + "<--\n"); } catch (Exception e) { trace(true,"Exception while communicating with server :\n" + e); trace(true,"-- program terminating"); return; } finally { try { // "Socket.close()" requires a catch clause if (socket != null) { trace(isTracing,"Closing socket"); socket.close(); } } catch (Exception e) { trace(true,"Exception when closing socket:\n" + e.toString()); } } } }