Skip to content

IOException in Java 8 when reading PKCS12 keystore created with keytool from OpenJDK16


keytool from OpenJDK16 creates PKCS12 keystore files that cannot be read from Java 8, 9, 10 and 11. Is this a bug? How to create a PKCS12 keystore that works with Java 8?


I build a Maven project which produces an executable JAR file that must run on any JRE from version 8 to version 16. That JAR file spawns an HTTPS server (using

During the build, I use keytool to generate a key pair and store it in a PKCS12 keystore that is bundled in the JAR (actually, I’m using keytool-maven-plugin):

$ /path/to/jdk16/bin/keytool -genkeypair -keystore /tmp/keystore.p12 -storepass password -storetype PKCS12 -alias https -dname "CN=localhost, OU=My HTTP Server, O=Sentry Software, C=FR" -keypass password -validity 3650 -keyalg RSA -sigalg SHA256withRSA

The Java code uses this automatically-generated keystore to start the HTTPS server:

// initialize the HTTPS server
httpsServer = HttpsServer.create(socketAddress, 0);

// initialize the keystore
KeyStore keyStore = KeyStore.getInstance("PKCS12");

// Load the self-certificate that is bundled with the JAR (see pom.xml)
InputStream ksStream = this.getClass().getResourceAsStream("/keystore.p12");
keyStore.load(ksStream, "password".toCharArray()); // Exception here

// Rest of the code (only for context purpose)

// setup the key manager factory
String defaultKeyManagerAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultKeyManagerAlgorithm);
keyManagerFactory.init(keyStore, "password".toCharArray());

// setup the trust manager factory
String defaultTrustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(defaultTrustManagerAlgorithm);

// setup the HTTPS context and parameters
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

// Sets the default SSL configuration (no need for extra code here!)
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));


When the JAR is build with a OpenJDK 16 JDK (and keytool from OpenJDK 16 is used) and then executed in a Java 8 JRE, we get this exception on keyStore.load():

IOException: parseAlgParameters failed: ObjectIdentifier() -- data isn't an object ID (tag = 48)

When the same JAR is executed in OpenJDK 11.0.7+10, we get this exception:

IOException: Integrity check failed: Algorithm HmacPBESHA256 not available

However, when the same JAR is executed with OpenJDK 14, 15 or 16, no exception and everything works.

Here’s a table that summarizes the versions of keytool, and whether the PKCS12 key store created with each version of keytool can be loaded in various JRE versions:

JRE 8 JRE 11 JRE 14 JRE 16
keytool 8
keytool 11
keytool 14
keytool 15
keytool 16


Is this a bug in keytool, or in the KeyStore class?

How to create a PKCS12 key store using OpenJDK16 that will work when loaded with JRE 8?

What is HmacPBESHA256? I haven’t specified this algorithm in my keytool command line.


It’s not a bug in keytool or KeyStore. keytool in OpenJDK 16 has been improved to use more secure algorithms by default, which are not supported with Java 8 and Java 11 (see JDK-8228481).

2 options to solve the problem:

  • Use JKS instead of PKCS12 for the key store
  • Use the -J-Dkeystore.pkcs12.legacy option with keytool to set the keystore.pkcs12.legacy system property and force OpenJDK 16’s keytool to use the older algorithms (which are supported by Java 8 and 11)

For the keytool-maven-plugin Maven plugin, use the below configuration:

                            <dname>CN=localhost, OU=${}, O=Sentry Software, C=FR</dname>
                                <!-- Important! Use this to make sure the PKCS12 keystore can be used -->
                                <!-- with Java 8 and 11 -->
                                <!-- See -->
                                <!-- See -->

Note: All credits go to @dave_thompson_085