以下のコードで単純に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″]で書きます。

カテゴリー: 技術情報