Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8173956

KeyStore regression due to default keystore being changed to PKCS12

XMLWordPrintable

    • 9
    • b156
    • generic
    • generic
    • Verified

        FULL PRODUCT VERSION :
        java version "9-ea"
        Java(TM) SE Runtime Environment (build 9-ea+153)
        Java HotSpot(TM) 64-Bit Server VM (build 9-ea+153, mixed mode)


        ADDITIONAL OS VERSION INFORMATION :
        Any Java 9 platform. I used x64 Linux (Ubuntu 14.04) and x64 Windows Server 2008 R2.

        A DESCRIPTION OF THE PROBLEM :
        I believe this bug has been present since changeset 6427:1da93663f8f3 but it's a lot more obvious in Java 9 now that PKCS12 is the default KeyStore type. The bug is also visible on Java 8 if you're explicitly using PKCS12 rather than JKS.

        REGRESSION. Last worked in version 8u121

        ADDITIONAL REGRESSION INFORMATION:
        Any Java 1.4, 1.5, 1.6, or 1.7 works fine, as does 1.8 unless you're explicitly using PKCS12.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Execute the test code with -enableassertions

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Passed (or omitted "-enableassertions"?)

        ACTUAL -
        X509TrustManager has no trust roots (!?): sun.security.ssl.X509TrustManagerImpl@224edc67
        Exception in thread "main" java.lang.AssertionError: Oh where, oh where has my little cert gone?
                at Bug8079616OnceMoreWithFeeling.main(Bug8079616OnceMoreWithFeeling.java:37)


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.security.KeyStore;
        import java.security.KeyStoreException;
        import java.security.NoSuchAlgorithmException;
        import java.security.cert.X509Certificate;
        import java.util.Collections;
        import javax.net.ssl.TrustManager;
        import javax.net.ssl.TrustManagerFactory;
        import javax.net.ssl.X509TrustManager;


        /**
         * KeyStore regression in Java 9.
         * <p>
         * This code works on Java 1.4, 1.5, 1.6, 1.7 and 1.8 but fails on Java 9
         * because the default KeyStore type is now PKCS12. It also fails on 1.8
         * if the KeyStore type is explicitly chosen to be PKCS12.
         */
        public class Bug8079616OnceMoreWithFeeling {

            public static void main(String[] ignored) throws Exception {

                // The first few lines below are just setup, not part of the test
                KeyStore pleaseUseCACerts = null;
                X509Certificate testCert = gimmeACert(pleaseUseCACerts);
                assert testCert != null;

                // Test code starts here
                String storeType = KeyStore.getDefaultType(); // or hard-code "pkcs12"
                KeyStore p12 = KeyStore.getInstance(storeType);
                p12.load(null, null);

                p12.setCertificateEntry("testCert", testCert);
                assert p12.size() == 1;
                assert Collections.list(p12.aliases()).size() == 1;

                X509Certificate check = gimmeACert(p12);
                assert check != null: "Oh where, oh where has my little cert gone?";
                assert check.equals(testCert);

                System.out.println("Passed (or omitted \"-enableassertions\"?)");
            }

            static X509Certificate gimmeACert(KeyStore storeOrNull) {
                TrustManager[] reallyOnlyOne;

                try {
                    TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                        TrustManagerFactory.getDefaultAlgorithm());
                    tmf.init(storeOrNull);
                    reallyOnlyOne = tmf.getTrustManagers();
                } catch (NoSuchAlgorithmException bogus) {
                    throw new AssertionError(bogus);
                } catch (KeyStoreException bogus) {
                    throw new AssertionError(bogus);
                }

                // Stick with pre-1.5 syntax to allow execution on 1.4
                for (int i = 0; i < reallyOnlyOne.length; i++) {
                    TrustManager tm = reallyOnlyOne[i];
                    if (tm instanceof X509TrustManager) {
                        X509Certificate[] certs =
                            ((X509TrustManager) tm).getAcceptedIssuers();
                        if (certs.length > 0) {
                            return certs[0];
                        } else {
                            System.err.println(
                                "X509TrustManager has no trust roots (!?): " + tm);
                            // ... which would lead to hair-pulling later in SSL code
                        }
                    }
                    // TODO: Else log somewhat surprising non-X.509 TrustManager
                }
                return null; // (Evil if this was an API, but fine for this test)
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Eschew Java 9, or set the default KeyStore type back to JKS, or explicitly use KeyStore.getInstance("JKS")

              vinnie Vincent Ryan
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: