SSL Server Sockets SSL Client and Server Sockets

The generic SSL sockets utilize several default options, including the protocol version used TLS 1.0, which also supports SSL 3.0 and the default key and trust managers. If you want to change any of these options, you must use an instance of the SSLContext class com.sun.net.ssl.SSLContext . This is often necessary, although it moves us away from a strictly protocol−independent socket factory paradigm. The SSLContext class is an engine class; it provides the following methods: public static SSLContext getInstanceString protocol public static SSLContext getInstanceString protocol, Provider provider public static SSLContext getInstanceString protocol, String provider Obtain an SSL context that implements the given protocol, optionally by consulting only the given provider. In Suns implementation of JSSE, the protocol must be TLS, TLSv1, SSL, or SSLv3. Since later versions of the protocol can support earlier versions, the string TLS provides the most generic instance of an SSL context. If the given algorithm cannot be found, a NoSuchAlgorithmException is thrown. If the given provider cannot be found, a NoSuchProviderException is thrown. public final String getProtocol Return the protocol supported by this context. public final Provider getProvider Return the provider that supplied the implementation of this context. public final void initKeyManager[] km, TrustManager[] tm, SecureRandom random Initialize this context with the given key managers, trust managers, and random number generator. Any or all of these parameters may be null , in which case default, internal implementations are used. If the context cannot be initialized, a KeyManagementException is thrown. public final SSLSocketFactory getSocketFactory Return a factory that produces SSL sockets based on the parameters of this context. public final SSLServerSocketFactory getServerSocketFactory Return a factory that produces SSL server sockets based on the parameters of this context. Typically, you use an SSL context so you can specify a new key manager or trust manager in the init method. Well see how to do that next.

14.4.1 Working with Key Managers

In our first server, we used the default key manager. The default key manager reads the keystore specified by the javax.net.ssl.keyStore property and finds the first alias in that keystore that has a key appropriate for use with the algorithm the server socket wants to use. Details on how the server socket selects an algorithm are given later in this chapter, but in essence the server will find the first RSA key or the first DSA key, and so on. The alias that is chosen is arbitrary, as it depends upon the order in which the aliases are returned via a hashtable enumeration. If you want to use a different keystore, or if you want to make sure that you use a particular alias, you must interact with the key manager. In the first case, you can simply initialize the default key manager with an appropriate keystore. In the second case, you must write your own key manager. Well look at both of those cases now. The default key manager is obtained via the KeyManagerFactory class com.sun.net.ssl.KeyManagerFactory , which contains the following methods: public static final String getDefaultAlgorithm Return the default algorithm for key managers. In Suns implementation of JSSE, this returns the string SunX509. You can change the default algorithm by changing the sun.ssl.keymanager.type property in the JREHOMElibsecurityjava.security file in which case you must have a third−party security provider that implements that algorithm. public final String getAlgorithm Return the name of the algorithm that this instance of the key manager factory implements. public static final KeyManagerFactory getInstanceString algorithm public static final KeyManagerFactory getInstanceString algorithm, Provider provider public static final KeyManagerFactory getInstanceString algorithm, String provider Obtain a key manager factory that implements the given algorithm, optionally by consulting only the given provider. With the security provider that comes with Suns implementation of JSSE, the algorithm must be SunX509. A NoSuchAlgorithmException is thrown if the algorithm cannot be found; if the provider cannot be found a NoSuchProviderException is thrown. public final Provider getProvider Return the provider that supplied this key manager factory. public void initKeyStore ks, char[] password Initialize the key manager factory so that it obtains keys from the given keystore using the given password. Note that only one password is used in this method, so the keystore must use the same password for all the private keys it stores. Initialization may throw a KeyStoreException , a NoSuchAlgorithm−Exception , or an UnrecoverableKeyException . public KeyManager[] getKeyManagers Obtain the key managers that this factory supplies. These last two methods are the most important ones for our consideration. The init method allows us to specify a different keystore, and the getKey−Managers method gets the actual key managers that the SSL classes need. Heres how we can extend our original server so that it uses a different keystore than the one specified via the command−line property changes are again shown in bold: package javasec.samples.ch14; import java.io.; import java.net.; import java.security.; import javax.net.; import javax.net.ssl.; import com.sun.net.ssl.; public class SSLServerWithContext { public static void mainString[] args throws Exception { SSLContext sc = SSLContext.getInstanceTLS; KeyManagerFactory kmf = KeyManagerFactory.getInstanceSunX509; KeyStore ks = KeyStore.getInstancejceks; char[] password = args[1].toCharArray ; ks.loadnew FileInputStreamargs[0], null; kmf.initks, password; sc.initkmf.getKeyManagers , null, null; ServerSocketFactory ssf = sc.getServerSocketFactory ; ServerSocket ss = ssf.createServerSocket9096; while true { new SSLSimpleServerss.accept.start ; } } } Here, we create the SSL context and then obtain a key manager factory. The factory is initialized with the keystore that we load from the first argument on the command line. The keystore uses the second argument to look up its private keys. Once the context is initialized, we create the server socket factory from the context and obtain the server socket from that factory. As before, the server socket is actually an instance of the SSLServerSocket class, and the bulk of the program logic is still provided by the SSLSimpleServer class. In this case, all weve really done is gone from specifying the keystore via a property to specifying it on the command line. This server is run as follows: piccolo java javasec.samples.ch14.SSLServerWithContext HOME.keystore This code contains the outline to use if you have a nondefault keystore; notice, for instance, that were using the JCEKS algorithm as input to the getInstance method of the KeyStore class. Similarly, if there are other differences in the way you obtain keystores, or if youd rather not specify the command−line property, this code shows how to initialize the key manager. However, our server still will use an arbitrary alias from the keystore. So now well take this example one step further and develop a key manager that allows us to specify which alias in the keystore to use. To write our own key manager, we must develop a class that implements the X509KeyManager interface com.sun.net.ssl.X509KeyManager . This interface extends the KeyManager interface com.sun.net.ssl.KeyManager , which is an empty interface used for type identification. Because the KeyManager interface does not define an API, the implementation of a key manager is tightly coupled with the implementation of the SSLContext class in use. Suns implementation of the SSLContext class requires you to pass at least one key manager that implements the X509KeyManager interface in the key manager array passed to the init method; the first such class in the array is the one that the SSLContext class uses to look up keys. All other key managers in the array are ignored. If no appropriate key manager is present in the array no exception is thrown, but nothing will work either. If youre using a third−party security provider that defines a different SSLContext class, it may expect a different type of key manager. To write our key manager, we must implement the following methods of the X509KeyManager interface: public String[] getClientAliasesString keyType, Principal[] issuers 276