以下のコードで単純にServerSocketFactory#createServerSocket(int, int)を呼び出すと、
ServerSocketFactory tServerSocketFactory = SSLServerSocketFactory.getDefault();
ServerSocket tServerSocket = tServerSocketFactory.createServerSocket(8889, 10);
Socket tSocket = tServerSocket.accept();
証明書が無いという例外が起きます。
Exception in thread "main" javax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled. at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.checkEnabledSuites(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(Unknown Source) at jp.kurusugawa.research.serversocket.Server.main(Server.java:36)
この例外は、証明書が入っているキーストアを指定していないことが原因で起きています。
キーストアの指定方法は2種類あります。
1. システムプロパティを指定する。
具体的には、javax.net.ssl.keyStoreにKeyStoreのパスを、javax.net.ssl.keyStorePasswordにKeyStoreのパスワードを指定すればよいです。
VM引数で以下のように指定したり、
java -Djavax.net.ssl.keyStore=keystorepath -Djavax.net.ssl.keyStorePassword=changeit
セキュリティの問題がなければ、以下のようにJavaプログラムで指定してもよいです。
System.setProperty("javax.net.ssl.keyStore", "keystorepath");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
2. KeyStoreを自前でファイル等のInputStreamからロードしてSSLContextに設定する。
KeyStore tKeyStore = KeyStore.getInstance("JKS");
char[] tKeyStorePassword = "changeit".toCharArray();
tKeyStore.load(new FileInputStream("keystorepath"), tKeyStorePassword);
KeyManagerFactory tKeyManagerFactory = KeyManagerFactory.getInstance("SunX509");
tKeyManagerFactory.init(tKeyStore, tKeyStorePassword);
SSLContext tSSLContext = SSLContext.getInstance("TLS");
tSSLContext.init(tKeyManagerFactory.getKeyManagers(), null, null);
SSLServerSocketFactory tServerSocketFactory = tSSLContext.getServerSocketFactory();
ServerSocket tServerSocket = tServerSocketFactory.createServerSocket(8889, 10);
Socket tSocket = tServerSocket.accept();
KeyStoreをどうやって作るのかについては、次のエントリ[intlink id=”577″]で書きます。