0

Ich verbinde mich mit REST Webservice läuft auf Server mit Apache HttpClientBuilder. Der Client muss ein zu validierendes Zertifikat senden, und das Serverzertifikat wird auf der Clientseite im Truststore hinzugefügt. Ich spezifiziere mit Optionen -Djavax.net.ssl.keyStore, -Djavax.net.ssl.trustStore.Webservice-Aufruf mit Zertifikaten schlägt fehl mit Socket-Lesefehler

Allerdings bekomme ich unter Fehler, irgendwelche Hinweise? Ich bin mir nicht sicher, SSL-Handshake ist erfolgreich, aber es scheint ServerHelloDone und Found Certificate in Protokollen.

-Code

HttpClient client = HttpClientBuilder.create().build(); 
HttpGet request = new HttpGet("https://testmachine.com/retrieve/path"); 

// add request header 
request.addHeader(Constants.HTTP_HEADER_ACCEPT, Constants.MEDIA_TYPE_JSON); 

// request to SERVER 
HttpResponse response = client.execute(request); 

LOGS

[write] MD5 and SHA1 hashes: len = 16 
0000: 14 ........g...oJ..v... 
Padded plaintext before ENCRYPTION: len = 32 
0000: 14....... 
0010: 5A....... 
main, WRITE: TLSv1 Handshake, length = 32 
main, waiting for close_notify or alert: state 3 
main, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed 
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed 
%% Invalidated: [Session-3, SSL_RSA_WITH_RC4_128_MD5] 
main, SEND TLSv1 ALERT: fatal, description = unexpected_message 
Padded plaintext before ENCRYPTION: len = 18 
0000: 02 [email protected] 
0010: 31 8F            1. 
main, WRITE: TLSv1 Alert, length = 18 
main, Exception sending alert: java.net.SocketException: Software caused connection abort: socket write error 
main, called closeSocket() 
main, called close() 
main, called closeInternal(true) 
Apr 18, 2016 1:52:17 PM org.apache.http.impl.execchain.RetryExec execute 
INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://testmachine.com:443: Software caused connection abort: recv failed 
Apr 18, 2016 1:52:17 PM org.apache.http.impl.execchain.RetryExec execute 
INFO: Retrying request to {s}->https://testmachine.com:443 
Allow unsafe renegotiation: true 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
%% No cached client session 
*** ClientHello, TLSv1 

Antwort

0

Es ist wie keystore sieht gelesen wird nicht aus den Protokollen. Ich suspect, dass es ist, weil mein Zertifikat in der keystore ist ". p12" -Format und hat sein eigenes Passwort. Also musste ich die keystore und truststore explizit laden und SSLContext bauen, damit es funktioniert.

Eine wichtige Sache zu beachten ist, dass die privateKeyPassword Sie das certificate Passwort angeben müssen (und nicht das keystore Passwort, das die Tasteneingabe zu schützen ist).

.loadKeyMaterial(keyStore, privateKeyPassword.toCharArray()) 

Hier ist ein Teil des Codes, der das erklärt.

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    FileInputStream keyStream = new FileInputStream(keystoreFile); 
    try { 
     keyStore.load(keyStream, keystorePassword.toCharArray()); 
    } catch (Exception ex) { 
     System.err.println("Failed to load keystore: " + ex.toString()); 
     return; 
    } finally { 
     try { 
      keyStream.close(); 
     } catch (Exception ignore) { 
     } 
    } 

    // load keystore and truststore 
    SSLContext sslcontext = SSLContexts.custom() 
      .loadTrustMaterial(truststoreFile, truststorePassword.toCharArray(), 
        new TrustSelfSignedStrategy()) 
        .loadKeyMaterial(keyStore, privateKeyPassword.toCharArray())   
        .build(); 

    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
      sslcontext, 
      new String[] { "TLSv1" }, 
      null, 
      SSLConnectionSocketFactory.getDefaultHostnameVerifier()); 

    CloseableHttpClient httpclient = HttpClients.custom() 
      .setSSLSocketFactory(sslsf) 
      .build();