はじめに
次はクライアント証明書を使ってみる。ついでにオレオレのサーバ証明書に対応する。
概要
サーバの時と同様に keystore, truststore をそれぞれ指定して使用する。
keystore にはクライアント証明書(秘密鍵含む)、truststore にはクライアント証明書のCA局証明書、オレオレサーバ証明書のCA局証明書を入れておく。
クライアント証明書のCA局証明書は、サーバ側のtruststoreに読み込んだものと同じ。
SSLContext
手順としては標準のtruststoreを使う場合、クライアント編1と同じく SSLContext を取得、SSLSocketFactory を得て Socket を作る。
というわけで SSLContext と SSLSocketFactory を作る部分はこのようになる。大体サーバ側と同じ。
package sslclient;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.net.Socket;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.InputStream;
public class App
{
private static SSLContext secureSocketContext;
private static SSLSocketFactory secureSocketFactory;
private static void initSSL()
{
try (
FileInputStream p12_file = new FileInputStream("clientcert.p12");
FileInputStream jks_file = new FileInputStream("mytruststore.jks");
) {
char[] passphrase = "passphrase".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(p12_file, passphrase);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(jks_file, passphrase);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
secureSocketContext = SSLContext.getInstance("TLS");
secureSocketContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
secureSocketFactory = secureSocketContext.getSocketFactory();
}
catch (Exception e) {
System.out.println("initSSL exception: " + e.toString());
}
}
clientcert.p12 がクライアント証明書のファイル名、mytruststore.jks がクライアント証明書・サーバ証明書のCA局証明書が入っているものになる。
passphrase はそのパスワード。
SSLSocket
あとはSocketを作って通信できる。以下の例では localhost:8443 に接続する。
通信するだけであれば、特にSSLSocketとして扱う必要はなく、ただのSocketで問題ない。
SSLSocketの機能を使う場合は SSLSocket にキャストして使う。
try {
Socket sock = secureSocketFactory.createSocket("localhost", 8443);
OutputStream os = sock.getOutputStream();
InputStream is = sock.getInputStream();
.
.
.
}
catch (Exception e) {
System.out.println("exception: " + e.toString());
}
TLSバージョンについて
サーバの時と同様に、SSLSocketにもgetEnabledProtocols, setEnabledProtocolsがある。
Cipher Suites も同様。