title: Load CA root certificate at runtime in Java
body: <p><em>tl;dr: Using custom CA without adding it to persistent keystore.</em></p>
  
  <p>I am writing a Java application that should connect to a remote server using HTTPS. The code for the connection is ready, however the SSL certificate of the server was signed by <a href="https://www.startssl.com/" rel="noreferrer">StartSSL</a>, which is not in Java's CA root cert store.</p>
  
  <p>Using <a href="http://www.mkyong.com/java/java-https-client-httpsurlconnection-example/" rel="noreferrer">this code</a>, I get valid certificate information from websites like <code>https://www.google.com/</code>:</p>
  
  <pre class="lang-none prettyprint-override"><code>Response Code : 200
  Cipher Suite : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  
  Cert Type : X.509
  Cert Hash Code : -1643391404
  Cert Public Key Algorithm : RSA
  Cert Public Key Format : X.509
  
  Cert Type : X.509
  Cert Hash Code : 771393018
  Cert Public Key Algorithm : RSA
  Cert Public Key Format : X.509
  
  Cert Type : X.509
  Cert Hash Code : 349192256
  Cert Public Key Algorithm : RSA
  Cert Public Key Format : X.509
  </code></pre>
  
  <p>The same code throws a <code>SSLHandshakeException</code> for my domain (let's call it <code>https://www.example.com/</code>).</p>
  
  <p>Of course I could manually add the certificate to the keystore using <code>keytool</code> (maybe even with <code>Runtime.exec("keytool ...")</code>), but this is way to dirty. What I am planning now is to add the StartSSL root certificate to my application files for distribution and then loading it into some temporary keystore at runtime. This way the "real" keystore remains untouched.</p>
  
  <p>From what I have read <a href="https://stackoverflow.com/questions/10077714/adding-certificate-to-keystore-using-java-code/10077862#10077862">here</a> and <a href="https://stackoverflow.com/questions/1650596/how-do-i-import-a-new-java-ca-cert-without-using-the-keytool-command-line-utilit">here</a>, I will have to mess with some classes like <code>TrustManager</code>. I even found a way to <a href="https://stackoverflow.com/questions/1201048/allowing-java-to-use-an-untrusted-certificate-for-ssl-https-connection/1201102#1201102">completely turn off the validation</a>, but this is not what I want since it seems to eliminate the whole purpose of encrypted communication.</p>
  
  <p>I even found some lines of code that seem to do exactly what I want, but I cannot figure out how to call this method i.e. which values to pass as arguments:</p>
  
  <pre><code>public class SSLClasspathTrustStoreLoader {
      public static void setTrustStore(String trustStore, String password) throws Exception {
          TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
          KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
          InputStream keystoreStream = SSLClasspathTrustStoreLoader.class.getResourceAsStream(trustStore);
          keystore.load(keystoreStream, password.toCharArray());
          trustManagerFactory.init(keystore);
          TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
          SSLContext sc = SSLContext.getInstance("SSL");
          sc.init(null, trustManagers, null);
          SSLContext.setDefault(sc);
      }
  }
  </code></pre>
  
  <p>Has anyone been in a similar situation before? I will appreciate any advice on how to handle this problem. If you could even help me to get the above code running, I'd be really happy!</p>