1. 概要

このチュートリアルでは、SSLリクエストを発行するときに発生する可能性のある一般的な問題を見ていきます。

2. 証明書ストアエラー

JavaアプリケーションがリモートパーティとのSSL接続を開くときは常に、証明書を検証して、サーバーが信頼できるかどうかを確認する必要があります。 ルート証明書が証明書ストアファイルに含まれていない場合、セキュリティ例外が発生します:

Untrusted: Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

このファイルのデフォルトの場所は$JAVA_HOME / lib / security/cacerts。であることを覚えておく必要があります。

3. 自己署名証明書

非実稼働環境では、信頼されていない発行者によって署名された証明書を見つけるのが一般的です。これは、自己署名証明書として知られています。

信頼できない証明書の例は、https://wrong.host.badssl.com/またはhttps://self-signed.badssl.com/にあります。 いずれかのブラウザで両方のURLを開くと、セキュリティ例外が発生します。 それらをチェックして、証明書の違いを確認できます。

https://self-signed.badssl.com/を開いた後、ブラウザが不明な機関によって証明書が発行されたため、ブラウザが「CertAuthorityInvalid」エラーを返すことがわかります。 :

 

一方、https://wrong.host.badssl.com/を開くと、「CertCommon NameInvalid」エラーが発生します。これは、別のホスト名に対して証明書が発行されたことを示す別の種類のエラーです。提供されたものより:

 

JDK/JRE内で実行されているアプリケーションでも同じことが起こります。 これらのセキュリティ例外により、信頼できない当事者へのSSL接続を開くことができなくなります。

4. 証明書を信頼するための証明書ストアの管理

幸運なことに、 JDK / JREは、証明書ストアと対話してそのコンテンツを管理するためのツールを提供します。 このツールはKeytoolであり、 $ JAVA_HOME / bin /keytoolにあります。

重要な注意事項 keytool を操作するには、パスワードが必要です。 デフォルトのパスワードは「changeit」です。

4.1. 証明書のリスト

JVMの証明書ストアに登録されているすべての証明書のリストを取得するには、次のコマンドを発行する必要があります。

keytool -list -keystore $JAVA_HOME/lib/security/cacerts

これにより、次のようなすべてのエントリを含むリストが返されます。

Your keystore contains 227 entries

Alias name: accvraiz1
Creation date: Apr 14, 2021
Entry type: trustedCertEntry

Owner: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Issuer: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
....

4.2. 証明書を追加する

そのリストに証明書を手動で追加して、SSL要求を発行するたびに証明書が検証されるようにするには、次のコマンドを実行する必要があります。

keytool -import -trustcacerts -file [certificate-file] -alias [alias] -keystore $JAVA_HOME/lib/security/cacerts

例えば:

keytool -import -alias ss-badssl.com -keystore $JAVA_HOME/lib/security/cacerts -file ss-badssl.pem

4.3. カスタム証明書ストアパス

上記のいずれも機能しない場合は、Javaアプリケーションが別の証明書ストアを使用している可能性があります。 これを確認するために、Javaアプリケーションを実行するたびに使用する証明書ストアを指定できます。

java -Djavax.net.ssl.trustStore=CustomTrustStorePath ...

そうすることで、以前に編集した証明書ストアを使用していることを確認します。 それでも問題が解決しない場合は、VMオプションを適用してSSL接続をデバッグすることもできます。

-Djavax.net.debug=all

5. 自動化スクリプト

まとめると、プロセス全体を自動化するためのシンプルで便利なスクリプトを作成できます。

#!/bin/sh
# cacerts.sh
/usr/bin/openssl s_client -showcerts -connect $1:443 </dev/null 2>/dev/null | /usr/bin/openssl x509 -outform PEM > /tmp/$1.pem
$JAVA_HOME/bin/keytool -import -trustcacerts -file /tmp/$1.pem -alias $1 -keystore $JAVA_HOME/lib/security/cacerts
rm /tmp/$1.pem

スクリプトでは、最初の部分が最初の引数として渡されたDNSへのSSL接続を開き、証明書を表示するように要求していることがわかります。 その後、証明書情報は openssl を介してパイプ処理され、ダイジェストされてPEMファイルとして保存されます。

最後に、このPEMファイルは、DNSをエイリアスとしてkeytoolに証明書をcacertsファイルにインポートするように指示することで使用するファイルです。

たとえば、https://self-signed.badssl.comの証明書を追加してみることができます。

cacerts.sh self-signed.badssl.com

実行後、cacertsファイルに証明書が含まれていることを確認できます。

keytool -list -keystore $JAVA_HOME/lib/security/cacerts

最後に、新しい証明書がそこにあることがわかります。

#5: ObjectId: 2.5.29.32 Criticality=false
CertificatePolicies [
[CertificatePolicyId: [2.5.29.32.0]

Alias name: self-signed.badssl.com
Creation date: Oct 22, 2021
Entry type: trustedCertEntry

Owner: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Issuer: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Serial number: c9c0f0107cc53eb0
Valid from: Mon Oct 11 22:03:54 CEST 2021 until: Wed Oct 11 22:03:54 CEST 2023
Certificate fingerprints:
....

6. 証明書を手動で追加する

何らかの理由でopensslを使用したくない場合は、ブラウザを使用して証明書を抽出し、keytoolを介して追加することもできます。

Chromiumベースのブラウザーでは、https://self-signed.badssl.com/のようなWebサイトを開き、開発者ツール(WindowsおよびLinuxの場合はF12)を開きます。 次に、[セキュリティ]タブをクリックし、最後に[証明書の表示]をクリックします。 証明書情報が表示されます。

 

「詳細」タブに移動し、「エクスポート」ボタンをクリックして保存しましょう。 これがPEMファイルです。

 

最後に、keytoolを使用してインポートします。

$JAVA_HOME/bin/keytool -import -trustcacerts -file CERTIFICATEFILE -alias ALIAS -keystore $JAVA_HOME/lib/security/cacerts

7. 結論

この記事では、自己署名証明書をJDK/JRE証明書ストアに追加する方法について説明しました。 これで、Javaアプリケーションは、これらの証明書を含むサイトへのSSL接続を開くたびに、サーバー側を信頼できます。