There are many problems out there about SSLHandshakeException but still I am facing one of them. I am an absolute beginner regarding SSL/TLS, actually security in general.
My problem:
I am using the Java Eclipse Paho mqtt library (windows7, oracle jdk1.8.0_65). My mqtt client is supposed to connect to a mqtt broker using a secured channel. I am basically using this solution with small adaptations to make use of the latest Bouncy Castle library from here. There I read in the received files I got from IT (*.pem
CA certificate, a *.crt
client certificate and *.key
file) to set up the TrustManagerFactory
, KeyManagerFactory
and eventually create the SSLContext
to set the SocketFactory
in the MqttConnectionOptions
.
When switching on SSL debugging, and trying to connect I observe the following handshake operation:
ssl://myserver.org:8883
adding as trusted cert:
...
***
found key for : private-key
chain[0]
...
Client sends its hello:
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1447336773 bytes = { .. , .. }
...
Server send its hello:
*** ServerHello, TLSv1.2
RandomCookie: GMT: 572699079 bytes = { .. , .. } -- (strange time stamp here)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
Extension elliptic_curves, curve names: {secp256r1}
Extension ec_point_formats, formats: [uncompressed]
***
%% Initialized: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
MQTT Con: TESTCLIENT1, READ: TLSv1.2 Handshake, length = 6544
*** Certificate chain
chain [0] = [
...
Now after the server passed its certificate chain I just get the following:
***
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
MQTT Con: TESTCLIENT1, SEND TLSv1.2 ALERT: fatal, description = certificate_unknown
MQTT Con: TESTCLIENT1, WRITE: TLSv1.2 Alert, length = 2
MQTT Con: TESTCLIENT1, called closeSocket()
MQTT Con: TESTCLIENT1, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
MQTT Con: TESTCLIENT1, called close()
MQTT Con: TESTCLIENT1, called closeInternal(true)
...
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
MQTT Con: TESTCLIENT1, setSoTimeout(30000) called
After that it seems there is just another try, and the client just sends another *** ClientHello, TLSv1.2
where the server answers again with *** ServerHello, TLSv1.2
. But I do not receive the expected *** ServerHelloDone
.
Solutions I tried:
1.) Using the Java keytool -importcert -alias ca-file.alias -file myPem.pem
I imported the *.pem
into my truststore cacerts
(I don't even know if this is needed).
2.) I tried to follow up on this solution which just removes the TrustManager
, and does get me a bit further:
***
MQTT Con: TESTCLIENT1, READ: TLSv1.2 Handshake, length = 333
*** ECDH ServerKeyExchange
Signature Algorithm SHA1withRSA
...
*** CertificateRequest
Cert Types: RSA
Supported Signature Algorithms: SHA1withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA
Cert Authorities:
<Empty>
MQTT Con: TESTCLIENT1, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
matching alias: private-key
*** Certificate chain
chain [0] = [
...
*** ECDHClientKeyExchange
...
*** CertificateVerify
...
*** Finished
It really seems that it does get me through but 1.) that's not how it should be and 2.) then the mqtt client just does not return after the first publish
call.
My questions are now:
- How do I handle certificates and key files correctly in Java using the
TrustManagerFactory
,KeyManagerFactory
, etc.? - What in general could be the problem with my connection setup?