title: SSL connection from Java client (Eclipse Paho) to mosquitto broker: "unknown_ca"
body: <p>We are researching a push notifications platform for Android (a failover for Google's C2DM) 
  I am using the Eclipse Paho Java client to connect to mosquitto broker (1.0.3).  The broker is installed on a Ubuntu 12.04 (AWS EC2 instance)
  I successfully connected the client to the server using non encrypted TCP connection. 
  By the way, after tweaking kernel params, I was able to open 100K concurrent clients to one broker instance on a medium sized EC2 machine.  Good work, mosquitto!</p>
  
  <p>Now I am trying to set up a secured connection using SSL.  I want to authenticate the client using a client certificate.
  I followed the explanations in <a href="http://mosquitto.org/man/mosquitto-tls-7.html" rel="noreferrer">mosquito_tls page</a> and generated the keys and self-signed certificates for server and client. 
  Configured the server to use SSL.</p>
  
  <p>For the client part, I looked at the signature of mosquitto_tls_set and took note that it requires the CA certificate, client key and certificate files.
  I figured that the CA certificate is used for the client to authenticate the server, while the client key and certificate are used for the server to authenticate the client.
  Am I right?</p>
  
  <p>So I here is what I did on the Java side:</p>
  
  <ol>
  <li>Use bouncy castle to load the three abovementioned files.</li>
  <li>Put the CA certificate in a keystore and used it to create a TrustManagerFactory.</li>
  <li>Put the client key and certificate in another keystore and used it to create a 
  KeyManagerFactory.</li>
  <li>Created an SSLContext an initialized it with the two factories.</li>
  <li>Created an SSLSocketFactory from the SSLContext and passed it to the Paho's MqttConnectOptions</li>
  </ol>
  
  <p>When I do the connect, I get the following error from mosquitto</p>
  
  <pre><code>OpenSSL Error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
  Socket read error on client (null), disconnecting.
  </code></pre>
  
  <p>Edit:
  now I see on the client side the following exception</p>
  
  <pre><code>javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
  </code></pre>
  
  <p>Here's the full code </p>
  
  <pre><code>static SSLSocketFactory getSocketFactory (final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception
  { 
      Security.addProvider(new BouncyCastleProvider());
  
      PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile)))));
      X509Certificate caCert = (X509Certificate)reader.readObject();
      reader.close();
  
      reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(crtFile)))));
      X509Certificate cert = (X509Certificate)reader.readObject();
      reader.close();
  
      reader = new PEMReader(
              new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFile)))),
              new PasswordFinder() {
                  public char[] getPassword() {
                      return password.toCharArray();
                  }
              }
      );
      KeyPair key = (KeyPair)reader.readObject();
      reader.close();
  
      KeyStore caKs = KeyStore.getInstance("JKS");
      caKs.load(null, null);
      caKs.setCertificateEntry("ca-certificate", caCert);
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
      tmf.init(caKs);
  
      KeyStore ks = KeyStore.getInstance("JKS");
      ks.load(null, null);
      ks.setCertificateEntry("certificate", cert);
      ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
      //ks.setKeyEntry("public-key", key.getPublic(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
      kmf.init(ks, password.toCharArray());
  
      SSLContext context = SSLContext.getInstance("SSLv3");
      context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  
      return context.getSocketFactory();
  }
  </code></pre>
  
  <p>The mosquito.conf looks like this</p>
  
  <pre><code># general options
  pid_file /home/ubuntu/mosquitto.pid
  
  # persistence
  queue_qos0_messages false
  persistence false
  
  # logging
  log_dest stdout
  connection_messages true
  log_timestamp false
  
  # default listener
  # disable default listener (open only SSL listener)
  #port 1883
  #max_connections -1
  
  # SSL listener
  listener 1883
  cafile /home/ubuntu/etc/ca.crt
  certfile /home/ubuntu/etc/server.crt
  keyfile /home/ubuntu/etc/server.key
  require_certificate true
  use_identity_as_username true
  max_connections -1
  </code></pre>