Handshake failure Client Key Exchange, using a certificate chain

Bryan E picture Bryan E · Dec 7, 2016 · Viewed 6.9k times · Source

I am try to establish a 2 way TSL connection to a web service using Java, I have been given a pfx certificate with a private key and a certificate chain of 3 certificates. Here is the java code using spring framework:

    @Bean
public Client weatherClient(Jaxb2Marshaller marshaller) throws Exception {
    Client client = new Client();
    client.setDefaultUri(".....");
    client.setMarshaller(marshaller);
    client.setUnmarshaller(marshaller);

    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(keyStore.getInputStream(), keyStorePassword.toCharArray());

    LOGGER.info("Loaded keystore: " + keyStore.getURI().toString());
    System.out.println("Loaded keystore: " + keyStore.getURI().toString());

    keyStore.getInputStream().close();


    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//KeyManagerFactory.getDefaultAlgorithm()
    keyManagerFactory.init(ks, keyStorePassword.toCharArray());

    KeyStore ts = KeyStore.getInstance("PKCS12");
    ts.load(trustStore.getInputStream(), trustStorePassword.toCharArray());//
    LOGGER.info("Loaded trustStore: " + trustStore.getURI().toString());
    System.out.println("Loaded trustStore: " + trustStore.getURI().toString());

    trustStore.getInputStream().close();

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(ts);

    HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
    messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
    messageSender.setTrustManagers(trustManagerFactory.getTrustManagers()); 
    client.setMessageSender(messageSender);
    return client;
}

So far I get a ClientHello and and a ServerHello which sends a certificate, and I get a Found trusted certificate. Then there is a certificate request which doesn't find any certificates

*** CertificateRequest 
Cert Types: RSA, DSS 
Cert Authorities:
<CN=Thawte SSL CA, O="Thawte, Inc.", C=US>
....
....
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client  authentication
*** Certificate chain
<Empty>
***

I have added the certificates individually into the lib/security/cacerts. It seems that the first certificate exchange happens from cacerts keystore, as I get the same behaviour if that is the only place that the certificate is added. It seems that the request is looking for the certificate chain but is unable to find it, even though I have imported into the KeyStore object as a pkcs12 with a private key and a certificate chain. Any help would be appreciated

UPDATE

I am getting a handshake failure after ClientKeyExchange I presumed it was due to the above warning but I might be wrong about that.

*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
main, WRITE: TLSv1 Handshake, length = 269
SESSION KEYGEN:
PreMaster Secret:
....
....
0000: B0 E2 38 5E 40 4E 7C C5                            ..8^@N..
Server write IV:
0000: 44 40 45 E1 82 45 15 9B                            [email protected]..
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 109, 220, 225, 98, 98, 233, 48, 215, 61, 50, 58, 207 }
***
main, WRITE: TLSv1 Handshake, length = 40
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, handshake_failure
%% Invalidated:  [Session-1, SSL_RSA_WITH_3DES_EDE_CBC_SHA]

UPDATE

The mutual authentication works if I add the keystore as a variable -Djavax.net.ssl.keyStore= but with out adding the key store as a variable I get the following. The key store and trust store specified in the code are found and the certificate chain and trust store are shown in the debug

***
found key for : devcert
chain [0] = [
[
  Version: V3 ......

***
adding as trusted cert:
  Subject: 

Then an empty keystore is shown and JVM cacerts are used as trusted certificates.

keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trustStore is: /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=ubuntu

Then there is a server hello *** ServerHello, TLSv1 which for which a certificate is found

    ***
    Found trusted certificate:
but the Certificate Request does find a matching certificate as above, unless it is added as a variable 
*** CertificateRequest 
Cert Types: RSA, DSS 
Cert Authorities:
<CN=Thawte SSL CA, O="Thawte, Inc.", C=US>
....
....
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client  authentication
*** Certificate chain
<Empty>
***

Behaviour with the keystore added as a varible -Djavax.net.ssl.keyStore=

*** ServerHelloDone
matching alias: devcert
*** Certificate chain
chain [0] = [
[
  Version: V3

I am wanting to use the keystore and truststore from the program code, as want to be able to look at dynamically changing it later

Answer

user207421 picture user207421 · Dec 7, 2016

You should not have been given a private key. This is already a major security breach. The actual problem is that the certficate is either not signed by the CAs mentioned in the CertificateRequest message or that it isn't of a type mentioned in it.