Подтвердить что ты не робот

Ошибка подключения SSL для Java 7

Я пытаюсь создать SSL-соединение с удаленным сервером с использованием Java 7, и я получаю следующее исключение:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
    at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
    at java.io.BufferedWriter.flush(BufferedWriter.java:254)
    at ssl7.Client.main(Client.java:22)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:482)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)

Когда я повторно запускаю код с помощью Java 6, исключений нет. Я нашел ссылки на эту проблему в другом месте на StackOverflow, но моя ситуация возникает с завихрением. Клиентский код, который не работает с Java 7,

public class Client {

    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        try {
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("login.solon.com", 443);    
            OutputStream outputstream = sslsocket.getOutputStream();
            OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
            BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
                bufferedwriter.write("hello\n");
                bufferedwriter.flush();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

Когда я добавляю строку

sslsocket.setEnabledCipherSuites(new String[] {"SSL_RSA_WITH_RC4_128_MD5"});

после создания сокета, он работает.

теперь, SSL_RSA_WITH_RC4_128_MD5 существует в исходном наборе наборов шифров, поэтому все, что я сделал, это добавить ограничения. Ограничение наборов шифров не является жизнеспособным решением в долгосрочной перспективе. Может ли кто-нибудь объяснить, что здесь происходит?

Полный журнал отладки:

keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trustStore is: C:\Temp\keystore\clientkeystore
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=W, OU=D, O=S, L=H, ST=I, C=IL
  Issuer:  CN=W, OU=D, O=S, L=H, ST=I, C=IL
  Algorithm: DSA; Serial number: 0x4a6e05b7
  Valid from Mon Oct 07 10:22:54 EEST 2013 until Sun Jan 05 09:22:54 EET 2014

adding as trusted cert:
  Subject: CN=login.solon.com, OU=Domain Validated, OU=Thawte SSL123 certificate, OU=Go to https://www.thawte.com/repository/index.html
  Issuer:  CN=Thawte DV SSL CA, OU=Domain Validated SSL, O="Thawte, Inc.", C=US
  Algorithm: RSA; Serial number: 0x3012ec22473f20aa2cdc4bf7fe2d22f4
  Valid from Wed Feb 13 02:00:00 EET 2013 until Thu Apr 14 02:59:59 EEST 2016

adding as trusted cert:
  Subject: CN=W, OU=D, O=S, L=H, ST=I, C=IL
  Issuer:  CN=W, OU=D, O=S, L=H, ST=I, C=IL
  Algorithm: RSA; Serial number: 0x5864235a
  Valid from Mon Oct 07 10:28:06 EEST 2013 until Sun Jan 05 09:28:06 EET 2014

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: true
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1381093608 bytes = { 221, 239, 107, 239, 150, 213, 224, 210, 101, 229, 42, 58, 92, 9, 151, 0, 128, 105, 0, 55, 53, 224, 90, 111, 130, 175, 61, 121 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
[write] MD5 and SHA1 hashes:  len = 149
0000: 01 00 00 91 03 01 52 52   D1 E8 DD EF 6B EF 96 D5  ......RR....k...
0010: E0 D2 65 E5 2A 3A 5C 09   97 00 80 69 00 37 35 E0  ..e.*:\....i.75.
0020: 5A 6F 82 AF 3D 79 00 00   2A C0 09 C0 13 00 2F C0  Zo..=y..*...../.
0030: 04 C0 0E 00 33 00 32 C0   07 C0 11 00 05 C0 02 C0  ....3.2.........
0040: 0C C0 08 C0 12 00 0A C0   03 C0 0D 00 16 00 13 00  ................
0050: 04 00 FF 01 00 00 3E 00   0A 00 34 00 32 00 17 00  ......>...4.2...
0060: 01 00 03 00 13 00 15 00   06 00 07 00 09 00 0A 00  ................
0070: 18 00 0B 00 0C 00 19 00   0D 00 0E 00 0F 00 10 00  ................
0080: 11 00 02 00 12 00 04 00   05 00 14 00 08 00 16 00  ................
0090: 0B 00 02 01 00                                     .....
main, WRITE: TLSv1 Handshake, length = 149
[Raw write]: length = 154
0000: 16 03 01 00 95 01 00 00   91 03 01 52 52 D1 E8 DD  ...........RR...
0010: EF 6B EF 96 D5 E0 D2 65   E5 2A 3A 5C 09 97 00 80  .k.....e.*:\....
0020: 69 00 37 35 E0 5A 6F 82   AF 3D 79 00 00 2A C0 09  i.75.Zo..=y..*..
0030: C0 13 00 2F C0 04 C0 0E   00 33 00 32 C0 07 C0 11  .../.....3.2....
0040: 00 05 C0 02 C0 0C C0 08   C0 12 00 0A C0 03 C0 0D  ................
0050: 00 16 00 13 00 04 00 FF   01 00 00 3E 00 0A 00 34  ...........>...4
0060: 00 32 00 17 00 01 00 03   00 13 00 15 00 06 00 07  .2..............
0070: 00 09 00 0A 00 18 00 0B   00 0C 00 19 00 0D 00 0E  ................
0080: 00 0F 00 10 00 11 00 02   00 12 00 04 00 05 00 14  ................
0090: 00 08 00 16 00 0B 00 02   01 00                    ..........
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
main, SEND TLSv1 ALERT:  fatal, description = handshake_failure
main, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 28                               ......(
main, called closeSocket()
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
    at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
    at java.io.BufferedWriter.flush(BufferedWriter.java:254)
    at ssl7.Client.main(Client.java:22)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:482)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
    ... 10 more

Спасибо.

4b9b3361

Ответ 1

Я видел такую ​​проблему раньше, когда использую сервер Ubuntu 12.04, на котором запущен сервер на основе Java, используя его пакет OpenJDK. (Возможно, это исправлено, поскольку я не могу воспроизвести проблему с последними обновлениями, но моя конфигурация может быть немного иной, я не помню.)

Это была проблема, описанная в этой проблеме Ubuntu.

По существу, проблема с расчетом EC на стороне сервера, что помешало правильному установлению соединения.

Существует разница в порядке предпочтений для наборов шифров между Java 6 и Java 7 ( см. обе таблицы).

Поскольку TLS_RSA_WITH_AES_128_CBC_SHA выше, чем любой набор шифров EC в порядке предпочтений в Java 6 (и поддерживается как клиентом, так и сервером), он будет выбран при подключении с клиентом Java 6.

Когда вы подключаетесь к клиенту Java 7, будут выбраны несколько наборов шифрования ЕС (например, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA или TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), и сервер начнет с этого делать (вам нужно будет увидеть журнал отладки рукопожатия серверная сторона, чтобы подтвердить это). Затем сервер будет выполнен с использованием процесса выбора набора шифра, но не будет идти дальше из-за последующей ошибки при попытке использовать этот набор шифров.

Если у вас есть некоторый контроль над сервером (и если он действительно работает на Java-сервере), попробуйте обновиться до последних пакетов JRE. Вы также можете попробовать исправления, предложенные в проблеме Ubuntu (особенно если это не используется PKCS # 11), или отключить набор шифров ECDHE в конфигурации сервера.

Ответ 2

С первого взгляда на конфигурацию вашего сервера (https://www.ssllabs.com/ssltest/analyze.html?d=login.solon.com) по сравнению с вашим списком доступных наборов шифров в Java7, кажется, что у вас есть только два принятых варианта для вашего набора шифров:

TLS_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA

Теперь TLS_DHE_RSA_WITH_AES_128_CBC_SHA считается слабым, но поскольку ваш сервер не заявляет о предпочтении для заказа, он может выбрать это, а затем не выполнить рукопожатие. Для Java6 вполне возможно, что это просто выбор более сильного пакета. Чем больше вариантов вы им дадите, тем больше шансов у вас есть шанс выбрать слабый шифр, поэтому, когда вы укажете один набор для использования, он преуспеет. (Хотя, глядя на конфигурацию вашего сервера, я не уверен, как вы добились успеха SSL_RSA_WITH_RC4_128_MD5, поскольку он, по-видимому, не поддерживается.) В этом процессе мыслей, возможно, вам стоит попытаться ограничить свои шифровые сюиты только:

TLS_RSA_WITH_AES_128_CBC_SHA

Или более конкретно:

sslsocket.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});

Ответ 3

Это проблема совместимости с Java 7 с хранилищами ключей. Преобразуйте файл хранилища ключей в .p12. Он должен работать с этим.

Ответ 4

Вы включили доверительное хранилище при выполнении клиента?

java -Djavax.net.ssl.trustStore=${resources}/localhost.truststore \
-Djavax.net.ssl.trustStorePassword=TRUSTSTORE_PASSWORD -jar client.jar com.acme.RunClient