title: Password-protected trust store created with keytool displays no entries if no password provided
body: <p>I am struggling with a difference in behavior between the way keytool creates a keystore (used as a trust store here) and imports a trusted certificate, VS the way other tools (e.g. <a href="http://portecle.sourceforge.net/" rel="nofollow noreferrer">portecle</a>, <a href="https://keystore-explorer.org/index.html" rel="nofollow noreferrer">kse</a>) do the same. </p>
  
  <p>Consider this command:</p>
  
  <pre><code>keytool -import -alias myAlias -file ./my_exported_server_cert.crt \
  -keystore ./my_truststore.jks
  </code></pre>
  
  <p>This will prompt me for a password, then create <code>my_truststore.jks</code> containing the certificate. </p>
  
  <p>Now, if I look inside, and provide the right password, the <code>myAlias</code> entry will be listed:</p>
  
  <pre><code>keytool -v -list -keystore ./my_truststore.jks -storeType jks -storepass myPass
  </code></pre>
  
  <p>or, programmatically...</p>
  
  <pre><code>try (InputStream is = new FileInputStream(new File("./my_truststore.jks"))) {
      KeyStore keyStore = KeyStore.getInstance("jks");
      keyStore.load(is, "myPassword".toCharArray());
      Iterator&lt;String&gt; it = keyStore.aliases().asIterator();
      while (it.hasNext()) System.out.println(it.next());
  }
  </code></pre>
  
  <p>However, if I <em>don't</em> provide a password (i.e. remove the <code>storepass</code> parameter from the <code>keytool</code> call and type return when prompted, or invoke <code>load</code> with <code>null</code> as the second argument in Java code), no entries are listed. </p>
  
  <p><code>keytool</code> provides a warning, but lists no entries. </p>
  
  <p>Now if I generate a trust store and import the certificate the same way with either portecle or kse, set a password, and run the checks again without providing a password, <code>myAlias</code> is still listed as an entry (<code>keytool</code> displays a warning as expected, but does also display the certificate). </p>
  
  <p>My debatable understanding of the matter is that a password is less relevant to <em>read</em> the contents of a trust store (without much investigation I am also assuming that is why <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/TrustManagerFactory.html#init(java.security.KeyStore)" rel="nofollow noreferrer">TrustManagerFactory#init</a> does not take a password, contrary to <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/KeyManagerFactory.html#init(java.security.KeyStore,char%5B%5D)" rel="nofollow noreferrer">KeyManagerFactory#init</a>).</p>
  
  <p><strong>My question</strong> </p>
  
  <ul>
  <li>What is the reason for the difference in behavior? Aren't those tools using the same core APIs as <code>keytool</code> behind the scenes?</li>
  <li>Is there a way to parametrize <code>keytool</code> in order to generate a trust store that allows read visibility on the entries when queried with no password, as the other tools do?</li>
  </ul>
  
  <p><strong>Notes</strong></p>
  
  <p>I have replicated this behavior with <code>keytool</code> from:</p>
  
  <ul>
  <li>Oracle JDK 11</li>
  <li>Oracle JDK 12</li>
  <li>OpenJDK11</li>
  </ul>
  
  <p>When testing with <code>keytool</code> from Oracle JDK8, I notice the entry is found, although I get warnings when initially creating the keystore server-side, and also exporting the one certificate:</p>
  
  <blockquote>
    <p>The JKS keystore uses a proprietary format. It is recommended to
    migrate to PKCS12 which is an industry standard format using "keytool
    -importkeystore -srckeystore ./ora8_keystore.jks -destkeystore ./ora8_keystore.jks -deststoretype pkcs12"</p>
  </blockquote>
  
  <p>Furthermore, the SSL handshake using the truststore generated with <code>keytool</code> from Oracle JDK8 seems to just hang forever with no traces of failure. </p>
  
  <p>While debugging my Java code, I noticed the truststores generated by either tool and either JDK (including Oracle JDK8) were ultimately initialized through the factory as a dual format key store regardless of the factory argument used (<code>jks</code>), i.e. the keystore object was of class <code>sun.security.provider.JavaKeyStore$DualFormatJKS</code>, with an spi having <code>primaryType = JKS</code> and <code>secondaryType = PCKS12</code>.</p>
  
  <p>That last bit doesn't really help me understand, but it might be relevant somehow. </p>