javaのプログラムから、自己証明書等を利用したサイトにSSL接続する

javaのプログラムからSSLで接続する場合に、OpenSSH等で作成した自己証明書を使っているサイトを利用する場合があると思います。

特に、開発時など、正式な証明書が用意されていない時や、開発環境へのアクセスなどが考えられますね。

それ以外にも、javaが正式なルート証明書だと認識していない証明書を使っている場合には、以下のようなエラーが出て、接続に失敗してしまいます。

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
    at org.apache.http.conn.ssl.SSLSocketFactory.createLayeredSocket(SSLSocketFactory.java:446)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.updateSecureConnection(DefaultClientConnectionOperator.java:200)
    at org.apache.http.impl.conn.AbstractPoolEntry.layerProtocol(AbstractPoolEntry.java:277)
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.layerProtocol(AbstractPooledConnAdapter.java:142)
    at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:759)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:566)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:776)
    at com.batch.SLLTestBatch.main(SLLTestBatch.java:41)

このような場合は、javaを起動する際に、自己証明書の情報を含めたキーストアを指定してあげると、エラーを回避することができます。

早速、指定して起動する方法を。。。と行きたいところですが、少し準備が必要です。

まず、キーストアとは何でしょうか。

キーストアとは

キーストア (KeyStore)とは、鍵と証明書の情報を保管するためのファイルです。

ファイル全体がパスワードによって暗号化されています。

Javaアプリケーションを起動する際に、信頼できる証明書情報が格納されたファイルとして

このキーストアファイルを指定してあげると、アプリケーションは、それらの証明書を利用している

サイトを妥当なサイトとして信頼します。

デフォルトのキーストアの場所

キーストアは、通常、システムにインストールされたjreまたはjdkの配下にあります。

「C:Program FilesJavajre1.5.0_22libsecurity」など、自分の環境のjavaのフォルダの下の「libsecurity」を見てみましょう。

そこに、「cacerts」というファイルがあるはずです。これが、Javaが実行時にデフォルトで使用するキーストアになります。

もうおわかりですね。自己証明書を利用したサイトにJavaプログラムからアクセスするには、このデフォルトのキーストアに自己証明書を追加してあげるか、自己証明書入りのキーストアファイルを新たに作成して、起動時に、デフォルトのキーストアではなく、そちらのファイルを使用するように指定してあげればよいことになります。

どちらでも良いのですが、今回は、分かりやすさとメンテのしやすさのために、新たにファイルを作ることにしましょう。

追加する証明書の準備

始めに、キーストアにimportする、接続先サイトの証明書を用意しましょう。

もし、自分で作成した証明書で無い場合は、サイトにブラウザでアクセスし、証明書をエクスポートしてください。

説明のために、この証明書(DER X509(cer)形式)を「mycert.cer」とします。

キーストア作成

では、キーストアを作成します。

対象のサイトの証明書だけを格納したキーストアを作成してもよいのですが、すでにデフォルトのキーストアに格納されている証明書に追加したキーストアを作成した方が、ゆくゆくは何かと便利でしょうから、そうしてみます。

先程のデフォルトのキーストアファイル「cacerts」を複製して、リネームします。

今回は「cacerts_add」としました。

そして、以下のコマンドをコマンドプロンプトから入力します。

"C:Program FilesJavajre1.5.0_22binkeytool" -import -trustcacerts -file ./mycert.cer -alias ca -keystore ./cacerts_add

キーストアを操作するコマンドは「keytool」になります。

すると、

キーストアのパスワードを入力してください:
と聞かれますので、「changeit」と入力します。これは、デフォルトのキーストアのパスワードです。

この証明書を信頼しますか? [no]:
と聞かれますので、「yes」と入力します。

正しく追加されたかを確認するには、以下のコマンドを使いましょう。

"C:Program FilesJavajre1.5.0_22binkeytool" -v -list -keystore ./mycerts_added

作成したキーストアを使ってjavaプログラムを起動

では、作成したキーストアの方を使うように、javaプログラムの起動時に、VMの引数として以下の指定をしてみましょう。

-Djavax.net.ssl.trustStore=cacerts_add -Djavax.net.ssl.trustStorePassword=changeit

これで、自己証明書等のサイトでもjavaのプログラムから問題なく接続ができるようになります。