Java 11 выдает сообщение о неподдерживаемом рукопожатии: server_hello_done при HTTPS-соединении с сертификатом клиента

У нас есть Java-апплет (работающий под управлением Tomcat), который звонит третьим сторонам. Один из них использует сертификат клиента для аутентификации. Это работало под Java 8, но недавно мы обновили систему до Java 11, и она больше не работает. Ошибка

Неподдерживаемое сообщение рукопожатия: server_hello_done

(что странно, так как я думал, что server_hello_done является действительной частью рукопожатия)

У нас была проблема с хранилищем ключей Java после обновления. Службе не удалось сообщить, что это недействительный поток PCKS12. Список содержимого с помощью keytool работал, но с предупреждением

Предупреждение:

Хранилище ключей JKS использует собственный формат. Рекомендуется перейти на PKCS12, который является стандартным отраслевым форматом, используя "keytool -importkeystore -srckeystore /path/to/keystore -destkeystore /path/to/keystore -deststoretype pkcs12"

Мы использовали предложенную команду, и теперь она открывает хранилище ключей, но мы получаем ошибку рукопожатия.

Трассировка стека обратно к нашему коду:

Unsupported handshake message: server_hello_done
javax.net.ssl.SSLProtocolException: Unsupported handshake message: server_hello_done
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:126)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:446)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)

Мы используем http-клиент apache (org.apache.http.impl.client.CloseableHttpClient). Следующая строка в трассировке стека — это просто вызов client.execute() в нашем коде.

Он также включает

Caused by: java.lang.UnsupportedOperationException: Not supported yet.
        at java.base/sun.security.ssl.HandshakeHash$CloneableHash.archived(HandshakeHash.java:616)
        at java.base/sun.security.ssl.HandshakeHash$T12HandshakeHash.archived(HandshakeHash.java:546)
        at java.base/sun.security.ssl.HandshakeHash.archived(HandshakeHash.java:188)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyMessage.<init>(CertificateVerify.java:581)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyProducer.produce(CertificateVerify.java:740)
        at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
        at java.base/sun.security.ssl.ServerHelloDone$ServerHelloDoneConsumer.consume(ServerHelloDone.java:173)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)

Третья сторона подтверждает, что не видит в своих журналах "общего шифра", но говорит, что поддерживает широкий спектр шифров ("SSL3, TLS 1.0, 1.1 или 1.2. Шифры помечены как HIGH:MEDIUM:!aNULL: !eNULL:@STRENGTH"). Я думаю, что мы поддерживаем большинство из них, кроме SSL3. Насколько я знаю, у нас есть настройки по умолчанию в java 11 для таких. Пытался временно активировать SSLv3, но не смог подключиться (хотя с тех пор, как я попытался, я вообще не могу подключиться с этой машины (тайм-аут) даже после возврата, так что это может мало что сказать - я пробовал с тестовой машины, а не с рабочей для тот).

Любые идеи? Я на правильном пути, чтобы продолжать смотреть на шифры, или я что-то упускаю?


person Adam    schedule 28.12.2018    source источник
comment
TLS 1.3, завершенный в августе и реализованный в Java 11, больше не использует server_hello_done. Тем не менее, похоже, что это соединение 1.2 (согласуется с тем, что говорит «третья сторона»), и из трассировки стека проблема заключается не в SHD как таковой, а в нескольких шагах позже, в вычислении подписи клиента-аутентификации (что делает сообщение об исключении немного вводящим в заблуждение ). Из формата строки шифрования сервер представляет собой OpenSSL или ответвление, подобное Libre, и я не могу воспроизвести с Java 11.0.1 (Oracle Win64) OpenSSL 1.0.2 (d) или 1.1.0 (-) (оба ShiningLight). ...   -  person dave_thompson_085    schedule 29.12.2018
comment
... Не используйте SSL3, который был сильно взломан в течение нескольких лет (и является протоколом или версией, а не шифром [набором]). Вы можете попробовать TLS1.1 или 1.0 вместо 1.2; они используют несколько иной алгоритм подписи клиентской аутентификации, который, по крайней мере, близок к проблеме. Изменение шифров не поможет; это никак не влияет на эту часть рукопожатия, и если они не видят общих шифров, они видят что-то не так. Но я подозреваю, что это ошибка Java, и я не настроен на отладку 11, извините.   -  person dave_thompson_085    schedule 29.12.2018
comment
Да, я не планировал использовать SSLv3, я просто пытался активировать его в отчаянии :) Использование клиента командной строки openssl много говорит о SSL3, но заканчивается соединением TLS1.2   -  person Adam    schedule 30.12.2018


Ответы (1)


Оказалось, что нужно было всего лишь перезапустить tomcat! Но, поскольку это был производственный сервер, делающий много вещей, я не хотел делать это в качестве первого шага. Но это исправило.

Мое лучшее предположение о том, что произошло, было:

  • Хранилище ключей имело неправильный формат для обновленной версии Java.
  • Попытка использовать недопустимое хранилище ключей привела tomcat/java в какое-то странное состояние.
  • Обновление хранилища ключей позволило java использовать его, но оно все еще находилось в каком-то странном состоянии.
  • Перезапуск исправил.

Что действительно странно, так это то, что он вел себя одинаково даже с другим IP-адресом (я пытался использовать сторонний тестовый сервер) и с другим хранилищем ключей (я сделал копию обновленного хранилища ключей и сделал запрос, который использовал это). Первоначальной ошибкой было "Stream не является допустимым хранилищем ключей PKCS12", и трассировка стека вернулась к строке, которая пыталась открыть хранилище ключей в нашем коде. После исправления формата хранилища ключей он продвинулся дальше в нашем коде (трассировка стека теперь вернулась к client.execute()), но произошел сбой с сообщением _Unsupported handshake message: server_hello_done_.

Я создал копию всей папки tomcat (включая jre) с изначально исходным (недействительным) хранилищем ключей, изменил его для запуска на другом порту и запустил рядом с этим котом на той же машине. Он вел себя так же, но затем работал после перезагрузки. Сегодня утром я перезапустил основной сервис, и теперь он работает.

person Adam    schedule 02.01.2019