paho.mqtt.android icon indicating copy to clipboard operation
paho.mqtt.android copied to clipboard

android mqtt ssl connection not working in android 7

Open ghost opened this issue 7 years ago • 8 comments

Please fill out the form below before submitting, thank you!

  • [x] Bug exists Release Version 1.1.1 (Java Repository Master Branch)
  • [ ] Bug exists in Snapshot Version 1.1.2-SNAPSHOT (Android Service Repository Master Branch)
  • [ ] Bug is just in the Sample Application.

Android API Version Bug Seen on: 25

Android Version Bug Seen on: 7

Please also check that if you have found the bug in the Release version (1.1.1) that you check that it also exists in the Snapshot (1.1.2-SNAPSHOT) before raising a bug.

Description of Bug:

Mqtt SSL connection is not working in Android Nougat and this working well bellow android 7.

I am using following code to connect with mqtt:

final MqttAndroidClient mqttAndroidClient = new MqttAndroidClient(MainActivity.this, "ssl://" + pref.getMqttUrl(), clientId, persistence);

try {
     String clientId = MqttClient.generateClientId();

     MqttConnectOptions connectionOptions = new MqttConnectOptions();
     connectionOptions.setCleanSession(true);

    Log.e("Test", "ssl://" + pref.getMqttUrl());

    try {
        InputStream trustStoresIs = context.getResources().openRawResource(R.raw.ca_key);


        String trustStoreType = KeyStore.getDefaultType();
        KeyStore trustStore = KeyStore.getInstance(trustStoreType);
        trustStore.load(trustStoresIs, context.getString(R.string.bks_password).toCharArray());

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(trustStore);

        InputStream keyStoreStream = context.getResources().openRawResource(R.raw.user_cer_key);
        KeyStore keyStore = null;
        keyStore = KeyStore.getInstance("BKS");
        keyStore.load(keyStoreStream, context.getString(R.string.bks_password).toCharArray());

        KeyManagerFactory keyManagerFactory = null;
        keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, context.getString(R.string.bks_password).toCharArray());

        SSLContext context = SSLContext.getInstance("SSL");
        context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);

        SSLSocketFactory sslsocketfactory = (SSLSocketFactory) context.getSocketFactory();
        connectionOptions.setSocketFactory(sslsocketfactory);

    } catch (KeyManagementException | CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    mqttAndroidClient.connect(connectionOptions, null, new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken asyncActionToken) {
            Log.e("Mqtt","Connection Success!");

        }

        @Override
        public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
            Log.e("Mqtt","Connection Failure!");

        }
    });

    mqttAndroidClient.setCallback(new MqttCallback() {
        @Override
        public void connectionLost(Throwable cause) {
            Log.e("Mqtt","Connection was lost!");

        }

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {



        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
            System.out.println("mqtt Delivery Complete!");
        }

    });


} catch (Exception ex) {
    ex.printStackTrace();

}

Console Log output (if available):

Mqttjavax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

ghost avatar Aug 21 '17 10:08 ghost

This sounds like the certificate is not in the trust store, this is something that you would need to manage yourself by adding the certificate to the trust store.

jpwsutton avatar Aug 25 '17 12:08 jpwsutton

Did the issue resolve with the suggestion provided by @jpwsutton?

chintan-mishra avatar Sep 13 '17 14:09 chintan-mishra

I found android mqtt ssl connection working well in android 7,but return SSLHandshakeException below android 7,even if I set the return value of verify from HostnameVerifier interface true.Do you know how to solve this problem?

RamboWong2015 avatar Dec 09 '17 06:12 RamboWong2015

@RamboWong2015 try this https://github.com/eurbon/Paho-MQTT-Android-TCP-TLS-WSS-Example

l2dev avatar Dec 15 '17 15:12 l2dev

Hi How to get key file i.e. R.raw.ca_key and R.raw.user_cer_key?

sukhwinder-kaur avatar Jul 19 '18 06:07 sukhwinder-kaur

I try this code but getting Hadshake issue, can you please share update code. @RamboWong2015 @sukhwinder-kaur , i was use @eurbon code but i have 3 certificate like "cert_ca.pem" ,"cert_cert", "cert_priv" how to use in your code. can yu provide demo code please?

Thanks is Advance.

Rohinisatpute avatar Dec 09 '18 03:12 Rohinisatpute

I made it work.

You should combine the Certificate and the Private Key to form a BKS keystore (user_cer_key.bks) This keystore corresponds to
InputStream keyStoreStream = getResources().openRawResource(R.raw.user_cer_key); in the above code sample.

Below are commands of forming the BKS keystore:

  1. First, combine the Certificate and the Private Key to form a pkcs12 keystore openssl pkcs12 -export -inkey your_private_key.pem -in your_certificate.pem -out user_cer_key.p12

  2. and then change the user_cer_key.p12 keystore to BKS keystore format : keytool -importkeystore -srckeystore user_cer_key.p12 -srcstoretype pkcs12 -destkeystore user_cer_key.bks -deststoretype bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk15on-161.jar

The file bcprov-jdk15on-161.jar you can download from the Website of Bouncy Castle

frogoscar avatar Mar 27 '19 16:03 frogoscar

ANDROID 7.1.2

    Caused by: MqttException (0) - javax.net.ssl.SSLHandshakeException: Chain validation failed
                        	at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
                        	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:738)
                        	at java.lang.Thread.run(Thread.java:761)
                        Caused by: javax.net.ssl.SSLHandshakeException: Chain validation failed
                        	at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
                        	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:159)
                        	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:724)
                        	at java.lang.Thread.run(Thread.java:761) 
                        Caused by: java.security.cert.CertificateException: Chain validation failed
                        	at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:610)
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:444)
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:464)
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:401)
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:375)
                        	at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:304)
                        	at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
                        	at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
                        	at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:178)
                        	at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:596)
                        	at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
                        	at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
                        	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:159) 
                        	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:724) 
                        	at java.lang.Thread.run(Thread.java:761) 
                        Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
                        	at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:156)
                        	at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
                        	at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
                        	at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:606)
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:444) 
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:464) 
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:401) 
                        	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:375) 
                        	at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:304) 
                        	at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94) 
                        	at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88) 
                        	at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:178) 
                        	at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:596) 
                        	at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
                        	at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) 
                        	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:159) 
                        	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:724) 
                        	at java.lang.Thread.run(Thread.java:761) 

how to solve it?

longxf avatar Jul 06 '23 02:07 longxf