title: TLS connection from Java client to mosquitto MQTT broker
body: <p>I am trying to set up a a tls connection to an mqtt mosquitto broker.
  i generate keys and certificates following : <a href="https://mosquitto.org/man/mosquitto-tls-7.html" rel="nofollow noreferrer">https://mosquitto.org/man/mosquitto-tls-7.html</a></p>
  
  <p>then here is my code :</p>
  
  <pre><code>public class App {
      public static void main(String[] args) {
          String serverUrl = "ssl://129.6.60.24:8883";
          String caFilePath = "./src/main/resources/ca.crt";
          String clientCrtFilePath = "./src/main/resources/brokerCertificate.crt";
          String clientKeyFilePath = "./src/main/resources/ca.key";
          String mqttUserName = "cpcc";
          String mqttPassword = "1qaz!QAZ1qaz";
          MqttClient client;
  
          try {
              client = new MqttClient(serverUrl, "TestBedBroker");
              client.setCallback(new SimpleMqttCallBack());
              MqttConnectOptions options = new MqttConnectOptions();
              options.setUserName(mqttUserName);
              options.setPassword(mqttPassword.toCharArray());
              SSLSocketFactory socketFactory = SslUtil.getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, "1qaz!QAZ1qaz");
              options.setSocketFactory(socketFactory);
              System.out.println("starting connect the server...");
              client.connect(options);
              System.out.println("connected!");
              Thread.sleep(1000);
              client.disconnect();
              System.out.println("disconnected!");
  
          }
          catch (MqttException e) {
              e.printStackTrace();
          }
          catch (Exception e) {
              e.printStackTrace();
          }
      }
  
  }
  
  public class SslUtil {
      public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception {
          Security.addProvider(new BouncyCastleProvider());
  
          // load CA certificate
          X509Certificate caCert = null;
  
          FileInputStream fis = new FileInputStream(caCrtFile);
          BufferedInputStream bis = new BufferedInputStream(fis);
          CertificateFactory cf = CertificateFactory.getInstance("X.509");
  
          while (bis.available() &gt; 0) {
              caCert = (X509Certificate) cf.generateCertificate(bis);
              // System.out.println(caCert.toString());
          }
  
          // load client certificate
          bis = new BufferedInputStream(new FileInputStream(crtFile));
          X509Certificate cert = null;
          while (bis.available() &gt; 0) {
              cert = (X509Certificate) cf.generateCertificate(bis);
              // System.out.println(caCert.toString());
          }
  
          // load client private key
          PEMParser pemParser = new PEMParser(new FileReader(keyFile));
          Object object = pemParser.readObject();
          PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
          JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
          KeyPair key;
          if (object instanceof PEMEncryptedKeyPair) {
              System.out.println("Encrypted key - we will use provided password");
              key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
          } else {
              System.out.println("Unencrypted key - no password needed");
              key = converter.getKeyPair((PEMKeyPair) object);
          }
          pemParser.close();
  
          // CA certificate is used to authenticate server
          KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
          caKs.load(null, null);
          caKs.setCertificateEntry("ca-certificate", caCert);
          TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
          tmf.init(caKs);
  
          // client key and certificates are sent to server so it can authenticate
          // us
          KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
          ks.load(null, null);
          ks.setCertificateEntry("certificate", cert);
          ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[] { cert });
          KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
          kmf.init(ks, password.toCharArray());
  
          // finally, create SSL socket factory
          SSLContext context = SSLContext.getInstance("TLSv1.2");
          context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  
          return context.getSocketFactory();
      }
  }
  </code></pre>
  
  <p>but when i run my program i have :</p>
  
  <pre><code>PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  </code></pre>
  
  <p>So i Tried to add my certificates to the Java trust store as suggested by many posts but i got the same error and i have absolutely no clue of what i am missing.</p>