発生した問題
以下のようなJava8u65(Java8u144以前)で実行しているJavaプログラムにおいてHTTPS通信ができない。
ClientHello送信後にServerHelloが返却されず、TLSハンドシェイクに失敗する。
$ java -version
openjdk version "1.8.0_65"
OpenJDK Runtime Environment (build 1.8.0_65-b17)
OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode)
なぜ発生したのか
HTTPS通信を行う際にクライアント側で使用可能な暗号スイートが、サーバー側で許容可能な暗号スイートを含まなかったために発生した。
詳細
そもそも、HTTPS通信を行う際にはTCPハンドシェイクが行われた後にTLSハンドシェイクが行われます。
TLSハンドシェイクではこちらで図示されているように、クライアントからClientHelloメッセージの送信後、サーバーからServerHelloメッセージを受信します。
RFC2246の7.4.1.3. Server helloに記載されている通り、Client Helloで送信した使用可能な暗号化スイート一覧に許容可能な暗号化スイートが含まれない場合はServerHelloメッセージが返却されず、close_notifyアラートが返却されて通信が終了します。
7.4.1.3. Server hello
When this message will be sent:
The server will send this message in response to a client hello
message when it was able to find an acceptable set of algorithms.
If it cannot find such a match, it will respond with a handshake
failure alert.
https://www.ietf.org/rfc/rfc2246.txt
Java8u144以前ではJCE管轄ファイルを別途ダウンロードおよびインストールする必要があるのですが特にそういった対応がされていない状態だったため問題が発生しました。
解決方法
1.JCE無制限強度管轄ポリシーを適用する
JCE無制限強度管轄ポリシーの適用方法については以下の記事がわかりやすかったです。
https://pg.hatenadiary.com/entry/2017/11/08/070000
2.最新のJDKまたはJREを利用する
8u161以降であれば無制限の暗号化をデフォルトで使用できるようになっているため、可能であればJavaを最新化することで解決します。