Отключить проверку цепочки сертификации в двустороннем SSL

Я имею в виду второй ответ на этот вопрос:

Веб-служба Клиент (JAX-WS) в Weblogic(10.3) с двусторонним SSL не может выполнить рукопожатие

У меня есть клиентская программа, которая подключается к другому серверу A с помощью одностороннего SSL. Чтобы отключить проверку цепочки сертификатов, я использовал решение во втором ответе на вопрос выше, чтобы установить доверенный менеджер доверия. Это работает нормально.

Однако, когда клиентская программа подключается к другому серверу B с помощью двустороннего SSL, выдается следующее исключение.

java.net.SocketException: Software caused connection abort: recv failed
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
        at sun.security.ssl.InputRecord.read(InputRecord.java:503)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
        at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1769)
        at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:124
)
        at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1130
)
        at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHan
dshaker.java:1216)
        at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.ja
va:1128)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.jav
a:348)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.
java:1375)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403
)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387
)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:
559)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect
(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLC
onnection.java:1316)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLCo
nnection.java:1291)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Htt
psURLConnectionImpl.java:250)

Если я не установлю вседоверительный диспетчер доверия, я все равно смогу установить соединение с обоими серверами (будь то одностороннее или двустороннее SSL), при условии, что я укажу хранилище удостоверений и хранилище доверия:

System.setProperty("javax.net.ssl.keyStore", "path/to/your/key");
System.setProperty("javax.net.ssl.keyStorePassword", "your-keystore-password");
System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", "path/to/your/trust/keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "your-truststore-password");

Однако я все еще хочу отключить проверку цепочки сертификатов в двустороннем SSL. Установка вседоверенного менеджера доверия, похоже, не работает. Почему?

Заранее спасибо.


person user3573403    schedule 30.03.2017    source источник
comment
Если вы не хотите, чтобы это было безопасно, почему вы используете двустороннюю аутентификацию? Почему вы вообще используете SSL?   -  person user207421    schedule 30.03.2017
comment
Сервер на самом деле является внутренним в компании. Он обслуживает многих других клиентов. Мне, как клиенту, все равно, находится ли идентификатор сервера в моем доверенном хранилище. Безопасность не так важна, так как это внутренний сервер.   -  person user3573403    schedule 30.03.2017
comment
Это не отвечает ни на один из моих вопросов.   -  person user207421    schedule 04.04.2017
comment
Во-первых, я сказал, что не хочу, чтобы это было безопасно? Я использую SSL, поэтому, конечно, это безопасно. Все, что я хотел, это отключить проверку сервера. Это внутренний сервер, которому мы можем доверять.   -  person user3573403    schedule 05.04.2017


Ответы (2)


Однако я все еще хочу отключить проверку цепочки сертификатов в двустороннем SSL. Установка вседоверенного менеджера доверия, похоже, не работает. Почему?

сервер требует, чтобы вы предоставили идентифицирующий сертификат клиента. Если ваш клиент не предоставляет сертификат, который настроен для приема сервером, он отбрасывает вашу попытку подключения.

Вы не можете изменить это в клиенте - вообще.

Протокол SSL разработан таким образом, что если клиент или сервер требуют, чтобы другая сторона идентифицировала себя с помощью сертификата, он не может быть изменен стороной, которая должна предоставить сертификат.

person Andrew Henle    schedule 30.03.2017
comment
Вы не понимаете, о чем я прошу. Я не хочу, чтобы клиентская программа проверяла сертификат сервера. Я не пытаюсь помешать серверу проверить сертификат клиента. - person user3573403; 30.03.2017

Теперь я знаю, в чем проблема. В решении, указанном в ссылке, есть следующие строки для установки доверительного менеджера:

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}

Проблема заключается в вызове sc.init. Первый параметр — это список ключевых менеджеров. По крайней мере, один диспетчер ключей необходим для возврата идентификатора клиента, чтобы его можно было отправить на сервер для аутентификации клиента. В приведенных выше кодах для диспетчеров ключей установлено значение null, что означает отсутствие идентификатора клиента, который можно отправить на сервер для проверки подлинности клиента. Вот почему он не пройдёт аутентификацию клиента, но пройдёт аутентификацию сервера (поскольку установлен доверительный менеджер доверия).

Вот как мы можем инициализировать хранилище ключей идентификации и установить его в контексте SSL:

KeyStore keyStore = KeyStore.getInstance("JKS");
FileInputStream fileInputStream = new FileInputStream("identity key store full path name");
keyStore.load(fileInputStream, "identity key store password".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "identity key store password".toCharArray());
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
sc.init(keyManagers, trustAllCerts, new java.security.SecureRandom());
person user3573403    schedule 04.04.2017