公開鍵証明書は本人性に関する問題を解決します。暗号化だけでもセキュアな接続をセットアップするには十分ですが、会話しているサーバが、あなたが会話していると思っているサーバである保証はありません。リモートサーバの本人性を検証する手段がなければ、攻撃者は依然としてリモートサーバとして居座り続けて、セキュアな接続をリモートサーバにフォワードすることができます。
公開鍵証明書はパスポートシステムとして考えるのがもっとも良い方法です。証明書は、偽造することが困難な方法で情報の運搬に関する情報を確立するために使われます。これが、証明書の検証がとても重要である理由です: すべての 証明書を受け入れることは、攻撃者の証明書さえ盲目的に受け入れてしまうことを意味します。
JDK 8 に付属するバージョンのキーツールを使います:
以下の例では、CA の使い方、またはホスト名のための証明書を、キーツール 1.8 を使って作ります。
pwgem を使ってランダムなパスワードを作ります (Mac の場合は brew install pwgen
):
ホスト名検証のために、ホスト名が登録された DNS サーバが必要になります。この例では、ホスト名を example.com
と仮定します。
はじめの一歩は、example.com 証明書に署名する認証局を作成することです。ルート CA 証明書は、それが CA 証明書であることを示すいくつかの追加属性 (ca:true や keyCertSign) を持っており、トラストストアに保持されます。
example.com 証明書は、以下のハンドシェイクで example.com
サーバより提示されます。
以下のように表示されるはずです:
Alias name: example.com
Creation date: ...
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=example.com, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
Issuer: CN=exampleCA, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
注意: より詳しくは [[Configuring HTTPS|ConfiguringHttps]] の章を参照してください。
example.com が TLS 終端に Java を使用しておらず、nginx を使っている場合は、証明書を PEM フォーマットで出力する必要があります。
残念ながらキーツールは秘密鍵の情報を出力しないので、これを引っ張り出すために openssl をインストールする必要があります。
これで example.com.crt
(公開鍵証明書) と example.com.key
(秘密鍵) の両方が手に入ったので、HTTPS サーバをセットアップすることができます。
例えば、この鍵を nginx で使う場合は nginx.conf
を以下のように設定します:
ssl_certificate /etc/nginx/certs/example.com.crt;
ssl_certificate_key /etc/nginx/certs/example.com.key;
(次の クライアントの設定 で触れる) クライアント認証を使う場合、以下も追加する必要があります:
ssl_client_certificate /etc/nginx/certs/clientca.crt;
ssl_verify_client on;
サーバを確認することで、期待している証明書であることを確認できます:
keytool -printcert -sslserver example.com
注意: より詳しくは [[フロントエンド HTTP サーバの設定|HTTPServer]] の章を参照してください。
クライアントの設定は二箇所あります -- トラストストアの設定と、クライアント認証の設定です。
どのようなクライアントでも、example.com サーバの証明書が信頼できることを確認する必要がありますが、秘密鍵を確認する必要はありません。この証明書だけを含み、そしてこれをクライアントに手渡すトラストストアを生成しましょう。多くの Java クライアントは JKS フォーマットのトラストストアを好んでいます。
exampleca の trustedCertEntry
が確認できるはずです:
Alias name: exampleca
Creation date: ...
Entry type: trustedCertEntry
Owner: CN=exampleCA, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
Issuer: CN=exampleCA, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
exampletrust.jks
ストアはトラストマネージャで使われます。
play.ws.ssl {
trustManager = {
stores = [
{ path = "/Users/wsargent/work/ssltest/conf/exampletrust.jks" }
]
}
}
注意: より詳しくは [[トラストストアとキーストアの設定|KeyStores]] の章を参照してください。
クライアント認証はドキュメントが貧弱で曖昧になりがちですが、以下の手順によって成り立っています。
- サーバは、署名されたクライアント証明書を期待する CA を提示することで、クライアント証明書を要求します。この場合は、
CN=clientCA
(デバッグ例 を参照してください) がこれに当たります。 - クライアントは
chooseClientAlias
とcertRequest.getAuthorities
を使って、キーマネージャの中からclientCA
によって署名された証明書を探します。 - キーマネージャは
client
証明書をサーバに返します。 - サーバはこのハンドシェイクにおいて、さらに ClientKeyExchange を行います。
クライアント CA と署名したクライアント証明書を作成する手順は、サーバー証明書の生成と大部分で似ていますが、利便性のために単一のスクリプトを提供しています:
以下のような client
というエイリアスがあるはずです:
Your keystore contains 1 entry
Alias name: client
Creation date: ...
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=client, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
Issuer: CN=clientCA, OU=Example Org, O=Example Company, L=San Francisco, ST=California, C=US
そして、client.jks
をキーマネージャに配置します:
play.ws.ssl {
keyManager = {
stores = [
{ type = "JKS", path = "conf/client.jks", password = $PW }
]
}
}
注意: より詳しくは [[トラストストアとキーストアの設定|KeyStores]] の章を参照してください:
コマンドラインツールよりも、グラフィカルなツールで証明書を検査したい場合は Keystore Explorer や xca を使うことができます。Keystore Explorer は JKS フォーマットを認識するので特に便利です。このツールは、手動インストールするとよく良く動作し、出力ポリシーにちょっとした調整が必要です。
キーツールよりも柔軟なコマンドラインツールを使いたい場合は、マルチパート PEM フォーマット証明書と JKS を理解する java-keyutil を試してみてください。
最高のセキュリティを求める場合は、(キーツールでは -sigalg EC
であろう) 署名アルゴリズムに ECDSA を使うことを検討してください。ECDSA は "ECC SSL Certificate" としても知られています。
古いシステムとの互換性には、署名アルゴリズムに 2048 bit 鍵の RSA と SHA256 を使ってください。独自の CA 証明書を作成している場合は、4096 bit のルートを使用してください。