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")
|