title: connect android device via MQTT with ssl
body: <p>I have created an MQTT Broker and a client in java. It works perfectly using SSL too.
  With a broker server and a client both written in java using paho libs, enabling SSL is easy. We need just to swich the protocol in the url from tcp to ssl IE: ssl://.messaging.internetofthings.ibmcloud.com:8883 and setting some props in te src code:</p>
  
  <pre><code>java.util.Properties sslClientProps = new java.util.Properties();
  sslClientProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
  options.setSSLProperties(sslClientProps); 
  </code></pre>
  
  <p>on the SSLContext</p>
  
  <pre><code>SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
  sslContext.init(null, null, null);
  </code></pre>
  
  <p>Than a secure and encrypted connection is created (checked sniffing the packets with WireShark).</p>
  
  <p>Using a specific CA trusted certificate works well too (messaging.pem file)</p>
  
  <pre><code>CertificateFactory cf = CertificateFactory.getInstance("X.509");
  InputStream certFile = MqttHandler.class.getResourceAsStream("messaging.pem");
  Certificate ca = cf.generateCertificate(certFile);
  KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
  keyStore.load(null, null);
  keyStore.setCertificateEntry("ca", ca);
  TrustManager trustManager = TrustManagerUtils.getDefaultTrustManager(keyStore);
  SSLContext sslContext = SSLContextUtils.createSSLContext("TLSv1.2", null, trustManager);
  options.setSocketFactory(sslContext.getSocketFactory());
  </code></pre>
  
  <p><strong>I need to use an Android Client and a custom MQTT Java Server Broker</strong> (without using SSL, MQTT publish and subscribe works well from Android too).</p>
  
  <p>The trouble seems related with the creation of the <em>SSLSocketFactory</em> from Android.</p>
  
  <p>I did this tests: </p>
  
  <p>1) Setting SSL props (as I did in the src of the java client as reported above)</p>
  
  <p>2) passing the CA trusted certificate on Android client (as I did in the src of the java client as reported above)</p>
  
  <p>3) generate the key store from the trusted CA in BouncyCastle format (compatible with Android) as reported here <a href="http://rijware.com/accessing-a-secure-mqtt-broker-with-android/" rel="noreferrer">http://rijware.com/accessing-a-secure-mqtt-broker-with-android/</a> and pass the key store on Android client:</p>
  
  <pre><code>CertificateFactory cf = CertificateFactory.getInstance("X.509");
  InputStream keyStoreFile = getAssets().open("raw_key_file");
  //keystore trusted
  KeyStore keystoreTrust = KeyStore.getInstance("BKS");//Bouncy Castle format for Android
  keystoreTrust.load(keyStoreFile, "mykeystorepassword".toCharArray());
  TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  trustManagerFactory.init(keystoreTrust);
  SLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
  options.setSocketFactory(sslContext.getSocketFactory());
  </code></pre>
  
  <p>4) using local trust store (CA) and client certificate:</p>
  
  <pre><code>// use local trust store (CA)
  TrustManagerFactory tmf;
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  InputStream srvIn = getAssets().open("messaging.pem");
  Certificate ca = cf.generateCertificate(srvIn);
  KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
  keyStore.load(null, null);
  keyStore.setCertificateEntry("ca", ca);
  tmf = TrustManagerFactory.getInstance("X509");
  tmf.init(keyStore);
  // load client certificate
  KeyStore clientKeyStore = null;
  InputStream clIn = getAssets().open("raw_key_file");
  clientKeyStore = KeyStore.getInstance("BKS");
  clientKeyStore.load(clIn, "mykeystorepassword".toCharArray());
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
  kmf.init(clientKeyStore, "mykeystorepassword".toCharArray());
  SSLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  options.setSocketFactory(sslContext.getSocketFactory());
  </code></pre>
  
  <p>Unfortunally with all the tests I still getting this error: <strong>MqttException (0) - javax.net.ssl.SSLException: Connection closed by peer</strong></p>
  
  <pre><code>MqttException (0) - javax.net.ssl.SSLException: Connection closed by peer
  at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
  org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:604)
  at java.lang.Thread.run(Thread.java:841)
  Caused by: javax.net.ssl.SSLException: Connection closed by peer
  at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
  at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:89)
  at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:590)
  </code></pre>
  
  <p>Maybe I still confusing with the certificates process. How to create these from scratch and using on server and client side (creating the keystore in BouncyCastle format compatible with Android) ?
  Or Maybe I did something wrong using the SSLSocketFactory classes in Android... </p>
  
  <p>Thanks, any suggestion is really approciated.</p>