Клиент Java ssl / https с использованием самозаверяющего сертификата

Я пытаюсь написать https-клиент Java, используя jdk версии 1.6.0_32. У меня есть самозаверяющий общедоступный сертификат, который я импортировал в новое хранилище доверенных сертификатов. Проблема в том, что я продолжаю получать «Исключение в потоке» main »javax.net.ssl.SSLHandshakeException: удаленное соединение с удаленным хостом закрыто во время рукопожатия». Вывод отладки SSL выглядит следующим образом:

C:\Users\csheets\eclispe_workspace\sdpweb\InstallSSLCert>java TestCert
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: c:\users\csheets\4startrust.ts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: CN=4starserver.servehttp.com
Issuer:  CN=4STAR
Algorithm: RSA; Serial number: 0x200000001
Valid from Mon May 14 11:25:15 MDT 2012 until Tue May 14 11:25:15 MDT 2013

trigger seeding of SecureRandom
done seeding SecureRandom
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: 1320442869 bytes = { 175, 184, 30, 195, 10, 55, 219, 232, 23
, 237, 63, 239, 83, 49, 125, 80, 10, 174, 112, 210, 61, 53, 232, 66, 179, 22, 16
1, 80 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH
_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC
_SHA, SSL_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_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SH
A, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_
WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WI
TH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
***
main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: SSLv3 Handshake, length = 527
*** ServerHello, SSLv3
RandomCookie:  GMT: 1320442987 bytes = { 158, 143, 79, 29, 193, 160, 122, 201, 8
1, 67, 17, 26, 159, 243, 54, 202, 255, 156, 125, 121, 132, 174, 17, 202, 222, 65
, 252, 77 }
Session ID:  {131, 30, 0, 0, 6, 235, 145, 226, 5, 214, 118, 217, 18, 123, 46, 20
4, 51, 182, 211, 225, 48, 172, 95, 70, 144, 4, 178, 150, 166, 75, 166, 29}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Created:  [Session-1, SSL_RSA_WITH_RC4_128_SHA]
** SSL_RSA_WITH_RC4_128_SHA
*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: CN=4starserver.servehttp.com
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 129409122589634486230897608496688768265641316152022572826296995250983
  80968933262586507340653723460037384941316405007365056646964455523390263136350462
  59738068084572819329229707448458528878467480278641098016863640927986379246142644
  62745346179244207665720440347282685862962453661441013596685879879277368109494267

public exponent: 65537
Validity: [From: Mon May 14 11:25:15 MDT 2012,
           To: Tue May 14 11:25:15 MDT 2013]
Issuer: CN=4STAR
SerialNumber: [    02000000 01]

]
Algorithm: [SHA1withRSA]
Signature:
0000: 00 8E A1 F4 58 22 F2 C2   A9 1D C6 CB 5A 23 F5 A5  ....X"......Z#..
0010: 02 3A C9 FF 83 96 1A 13   3A 0F 59 D5 1E 1F 56 85  .:......:.Y...V.
0020: AB 4A 46 8D F3 43 E8 BA   B3 F9 B7 8C FB 76 AD D5  .JF..C.......v..
0030: 9F 15 47 DC 30 72 F9 BA   B1 FF DA 2C 25 89 FF 30  ..G.0r.....,%..0
0040: C4 4F BA D6 0C B9 30 10   B0 4B 74 EF 8A F4 5D F1  .O....0..Kt...].
0050: AC 2C 47 D9 C2 F5 A0 AF   CE 8B 76 53 36 A3 BE 11  .,G.......vS6...
0060: 7E BA 1F 4A 67 C1 69 EF   C3 E6 32 E2 0D 09 93 66  ...Jg.i...2....f
0070: 92 21 66 88 95 CA BD C8   FF CF 79 9D 7E F3 DC E0  .!f.......y.....

]
***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=4starserver.servehttp.com
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 129409122589634486230897608496688768265641316152022572826296995250983
80968933262586507340653723460037384941316405007365056646964455523390263136350462
59738068084572819329229707448458528878467480278641098016863640927986379246142644
62745346179244207665720440347282685862962453661441013596685879879277368109494267

 public exponent: 65537
 Validity: [From: Mon May 14 11:25:15 MDT 2012,
           To: Tue May 14 11:25:15 MDT 2013]
 Issuer: CN=4STAR
 SerialNumber: [    02000000 01]

 ]
Algorithm: [SHA1withRSA]
Signature:
0000: 00 8E A1 F4 58 22 F2 C2   A9 1D C6 CB 5A 23 F5 A5  ....X"......Z#..
0010: 02 3A C9 FF 83 96 1A 13   3A 0F 59 D5 1E 1F 56 85  .:......:.Y...V.
0020: AB 4A 46 8D F3 43 E8 BA   B3 F9 B7 8C FB 76 AD D5  .JF..C.......v..
0030: 9F 15 47 DC 30 72 F9 BA   B1 FF DA 2C 25 89 FF 30  ..G.0r.....,%..0
0040: C4 4F BA D6 0C B9 30 10   B0 4B 74 EF 8A F4 5D F1  .O....0..Kt...].
0050: AC 2C 47 D9 C2 F5 A0 AF   CE 8B 76 53 36 A3 BE 11  .,G.......vS6...
0060: 7E BA 1F 4A 67 C1 69 EF   C3 E6 32 E2 0D 09 93 66  ...Jg.i...2....f
0070: 92 21 66 88 95 CA BD C8   FF CF 79 9D 7E F3 DC E0  .!f.......y.....

]
*** ServerHelloDone
*** ClientKeyExchange, RSA PreMasterSecret, SSLv3
main, WRITE: SSLv3 Handshake, length = 132
SESSION KEYGEN:
PreMaster Secret:
0000: 03 00 07 86 97 89 23 A4   73 85 54 59 A4 76 DD 85  ......#.s.TY.v..
0010: 12 1A 28 1B 71 CC 7A B2   EE 0F 65 60 26 30 6C B4  ..(.q.z...e`&0l.
0020: B4 92 2D 15 50 51 E5 10   77 96 8E B0 4F 30 57 73  ..-.PQ..w...O0Ws
CONNECTION KEYGEN:
Client Nonce:
0000: 4F B4 5C F5 AF B8 1E C3   0A 37 DB E8 17 ED 3F EF  O.\......7....?.
0010: 53 31 7D 50 0A AE 70 D2   3D 35 E8 42 B3 16 A1 50  S1.P..p.=5.B...P
Server Nonce:
0000: 4F B4 5C 6B 9E 8F 4F 1D   C1 A0 7A C9 51 43 11 1A  O.\k..O...z.QC..
0010: 9F F3 36 CA FF 9C 7D 79   84 AE 11 CA DE 41 FC 4D  ..6....y.....A.M
Master Secret:
0000: 60 59 16 75 E0 5E 4B 64   D6 6B 56 18 9B F2 C8 7A  `Y.u.^Kd.kV....z
0010: F8 DF 65 C6 C0 12 92 62   15 A1 4E 5F 53 D3 02 EF  ..e....b..N_S...
0020: 9B EF ED FD 1E 01 61 6F   AC 39 E0 5B AD 87 BF 25  ......ao.9.[...%
Client MAC write Secret:
0000: C1 36 79 97 E6 71 22 D0   27 D0 41 88 F9 F5 8D C2  .6y..q".'.A.....
0010: EA A3 97 FB                                        ....
Server MAC write Secret:
0000: C4 00 15 49 31 29 B2 F3   06 90 59 F0 5A 4D 3D 45  ...I1)....Y.ZM=E
0010: 32 B2 B6 83                                        2...
Client write key:
0000: E6 46 87 A2 16 52 04 11   73 15 E8 23 9F E6 02 A3  .F...R..s..#....
Server write key:
0000: 04 63 1D 64 E7 25 FC E4   53 FC 43 04 33 3C ED 6E  .c.d.%..S.C.3<.n
... no IV used for this cipher
main, WRITE: SSLv3 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 61, 221, 238, 253, 97, 36, 152, 79, 254, 95, 226, 136, 55, 16, 2
07, 66, 58, 197, 233, 254, 125, 99, 11, 0, 138, 51, 139, 62, 175, 123, 52, 167,
131, 216, 245, 97 }
***
main, WRITE: SSLv3 Handshake, length = 60
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host close
d connection during handshake
main, SEND SSLv3 ALERT:  fatal, description = handshake_failure
main, WRITE: SSLv3 Alert, length = 22
main, called closeSocket()
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host clos
ed connection during handshake
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)

    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Un
known Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Sou
rce)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Sou
rce)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect
(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So
urce)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unkn
own Source)
    at TestCert.main(TestCert.java:92)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
    ... 9 more

Не знаю, как интерпретировать всю эту информацию, но похоже, что мой сертификат найден и ему доверяют - что означает ClientKeyExchange - может быть, сервер ожидает аутентификации клиента или это просто обмен информацией о сертификате. Кажется, что все хранилище ключей Java, доверенные сертификаты и самозаверяющие сертификаты создают много сложностей и путаницы - по крайней мере, для меня.

Мой тестовый клиентский код выглядит следующим образом:

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.*;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.security.*;

public class TestCert {
public static void main(String[] args) throws Exception {
    System.setProperty("javax.net.debug", "ssl");
    System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
    System.setProperty("javax.net.ssl.trustStore", "c:\\users\\csheets\\4startrust.ts");
    System.setProperty("javax.net.ssl.trustStorePassword", "mypassword");


    SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();

    URL url = new URL("https://4starserver.servehttp.com:777/?username=0&password=0&command=WEBAUTH&TRAN=2&MERCHANT=9999999999119911&FNAME=TONY&LNAME=PISCOPO&CC=4111111111111111&EXP=0613&AMOUNT=99.98");
    HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
    conn.setSSLSocketFactory(sslsocketfactory);

    InputStream inputstream = conn.getInputStream();
    InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
    BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

    String string = null;
    while ((string = bufferedreader.readLine()) != null) {
        System.out.println("Received " + string);
    }
}
}

Я пробовал и другие вещи, такие как создание собственных TrustManager и TrustManager, но это тоже не сработало. Будем очень благодарны любой помощи.

ОБНОВЛЕНИЕ: порт сервера был изменен на 443, чтобы его можно было протестировать с помощью Qualys SSL Lab. test, и я получил следующие результаты:

Common Error Messages

Connect timed out - server did not respond to our connection request
No route to host - unable to reach the server
Unable to connect to server - failed to connect to the server
Unrecognized SSL message, plaintext connection? - the server responded with plain-text HTTP on HTTPS port
Received fatal alert: handshake_failure - this is either a faulty SSL server or some other server listening on port 443; if the SSL version of the web site works in your browser, please report this issue to us
Known Issues

Could not generate DH keypair - due to a known problem with the underlying SSL library (Sun's JSSE implementation) we are unable to assess the sites that offer only DHE handshakes stronger than 1024 bits.

Странно то, что я, кажется, получаю ответ от сервера, если просто помещаю URL-адрес https://server.com/ в браузере - но на сервере явно кажется, что делается несколько запросов / подключений. Кажется, на стороне сервера что-то не так?


person csheets    schedule 17.05.2012    source источник


Ответы (3)


Ваш сертификат является доверенным (с использованием вашего настраиваемого хранилища доверенных сертификатов), это не проблема диспетчера доверия. Вам не нужно разрешать небезопасное повторное согласование (или указывать значение по умолчанию SSLSocketFactory).

Кажется, проблема с настройкой TLS, так как он работает с System.setProperty("https.protocols", "SSLv3");. У вас также возникнет проблема с рукопожатием, если вы принудительно -tls1 с помощью openssl s_client.

Если вы контролируете сервер, я бы предложил попробовать подключить его к порту 443 и протестировать через Тест Qualys SSL labs (более подробный и выявляет больше проблем, чем многие другие доступные тесты).

person Bruno    schedule 17.05.2012
comment
Таким образом, установка свойства https.protocols на SSLv3 работает! Я хотел бы понять это немного подробнее - что это на самом деле делает и чем это отличается от действия: SSLContext sslContext = SSLContext.getInstance (SSLv3); Я в порядке, просто устанавливаю системное свойство, если это по какой-то причине не является проблемой. Также спасибо за предупреждение о тестировании Qualys SSL labs - я не знал об этом. - person csheets; 18.05.2012
comment
SSLContext.getInstance(...) ... возвращает экземпляр, реализующий по крайней мере запрошенный протокол безопасного сокета. Возвращенный экземпляр может также реализовывать другие протоколы.. Напротив, https.protocols устанавливает явно включил протоколы на сокете, используемом HttpsURLConnection: это то, что используется для указания, какой из SSLv3 / TLSv1.x использовать. - person Bruno; 18.05.2012
comment
Обычно я предлагаю попробовать перейти на более высокие версии (с точки зрения SSLv3, TLSv1.0, TLSv1.1, ...), если сможете. В идеале в настоящее время SSLv3 должен исчезнуть, и мы должны стремиться использовать как минимум TLS 1.1 (среди прочего, для устранения уязвимости BEAST). В настоящее время немногие серверы не поддерживают TLS 1.0 (один из них - тот, который вы пытаетесь использовать). - person Bruno; 18.05.2012
comment
Большое спасибо за информацию - очень признателен. - person csheets; 18.05.2012
comment
Я обновил вопрос результатами теста Qualys SSL - похоже, что-то не так на стороне сервера? Во всяком случае, я думаю, что на данный момент я доволен настройкой SSLv3 явно для сокета через системное свойство https.protocols. Спасибо всем за помощь. - person csheets; 18.05.2012
comment
У меня похожая проблема. Пожалуйста, посмотрите на это. stackoverflow.com/questions/12822436/ - person Balconsky; 10.10.2012

Для тех, у кого есть подобная проблема: у меня также была проблема с использованием Java и SSL, когда на сервере был самоподписанный сертификат. Я пробовал использовать System.setProperty («https.protocols», «SSLv3»); как упоминалось в ответе. У меня не получилось. Но что-то похожее сработало: System.setProperty ("https.protocols", "TLSv1");

person user2367418    schedule 24.10.2014

Попробуйте реализовать класс X509TrustManager в своем основном классе, а затем:

    private static void trustAllHttpsCertificates() throws Exception {
       //  Create a trust manager that does not validate certificate chains:
       javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
       javax.net.ssl.TrustManager tm = new YourMainClass();
       trustAllCerts[0] = tm; 
       javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
       sc.init(null, trustAllCerts, null);
       javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

и переопределить это,

    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
       return;
    }

    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
       return;
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
       return null;
    }

Надеюсь помочь вам. :)

person hekomobile    schedule 17.05.2012
comment
Не отключайте проверку сертификата, это открывает двери для атак MITM. Кроме того, в этом вопросе указывается конкретное хранилище доверенных сертификатов (это правильный способ сделать это), и сертификат явно заслуживает доверия. - person Bruno; 17.05.2012
comment
Я на самом деле пробовал этот подход в целях тестирования, чтобы просто посмотреть, смогу ли я заставить что-то / что-нибудь работать - это не повлияло на меня по какой-то причине - wsa все еще получал ту же ошибку. Установка для свойства System https.protocols на SSLv3, похоже, работает, но не знаю почему, но пока продолжаю :-) Спасибо за помощь. - person csheets; 18.05.2012
comment
Привет, @csheets, класс TestCert для меня возвращает Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake. Думаю это проблемный сервер. Я тестировал инструменты X509TrustManager. Вам нужно вернуть или получить что-то? Например XML или файл ?. - person hekomobile; 18.05.2012
comment
Согласитесь - я думаю, что это тоже проблема сервера - кажется, что-то не совсем правильное на основе другого тестирования - см. Обновление в вопросе о результатах тестирования Qualys SSL. Но я думаю, что на данный момент у меня есть ответ - явная установка системного свойства https.protocols на SSLv3 - похоже, работает нормально без ошибок на клиенте или сервере. - person csheets; 18.05.2012