|
Duplicate :
|
|
|
Relates :
|
|
|
Relates :
|
jdk-14.0.2ADDITIONAL SYSTEM INFORMATION :
Mac OS X 10.14.1
OpenJDK 11.0.1
Oracle JDK 1.8.0_192
A DESCRIPTION OF THE PROBLEM :
A private key that has been saved to a PKCS12 keystore using custom PBE parameters in Java 8 (1.8.0_192) cannot be read in Java 11.0.1 and vice versa. It appears the ASN.1 encoding of the PBE parameters has incompatibly changed at some point between these two releases.
REGRESSION : Last worked in version 8u192
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a PKCS#12 keystore in Java 8 and add a private key entry using a custom PBE scheme:
KeyStore.PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(keyPair.getPrivate(),
new Certificate[] { cert });
keyStore.setEntry("server", privateKeyEntry,
new PasswordProtection("password".toCharArray(), "PBEWithHmacSHA512AndAES_256",
new PBEParameterSpec(salt, 100_000)));
Save the PKCS12 keystore to a file. Now try to load the same keystore and key from Java 11.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The key is loaded correctly without error.
ACTUAL -
Exception in thread "main" java.security.UnrecoverableKeyException: Private key not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: ObjectIdentifier() -- data isn't an object ID (tag = 42)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:373)
at java.base/sun.security.util.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:90)
at java.base/java.security.KeyStore.getKey(KeyStore.java:1057)
at PemTest.main(PemTest.java:72)
Caused by: java.io.IOException: ObjectIdentifier() -- data isn't an object ID (tag = 42)
at java.base/sun.security.util.ObjectIdentifier.<init>(ObjectIdentifier.java:257)
at java.base/sun.security.util.DerInputStream.getOID(DerInputStream.java:320)
at java.base/com.sun.crypto.provider.PBES2Parameters.parseKDF(PBES2Parameters.java:282)
at java.base/com.sun.crypto.provider.PBES2Parameters.engineInit(PBES2Parameters.java:267)
at java.base/java.security.AlgorithmParameters.init(AlgorithmParameters.java:312)
at java.base/sun.security.x509.AlgorithmId.decodeParams(AlgorithmId.java:132)
at java.base/sun.security.x509.AlgorithmId.<init>(AlgorithmId.java:114)
at java.base/sun.security.x509.AlgorithmId.parse(AlgorithmId.java:374)
at java.base/sun.security.pkcs.EncryptedPrivateKeyInfo.<init>(EncryptedPrivateKeyInfo.java:80)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:362)
... 3 more
---------- BEGIN SOURCE ----------
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.crypto.spec.PBEParameterSpec;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class Pkcs12Test {
public static void main(String[] args) throws Exception {
// *** RUN THIS AS JAVA 8 ***
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
SecureRandom secureRandom = SecureRandom.getInstanceStrong();
BigInteger serial = new BigInteger(159, secureRandom);
X500Name self = new X500Name("cn=localhost");
X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(self, serial,
new Date(), new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(3650)), self,
keyPair.getPublic());
X509CertificateHolder certHolder = certificateBuilder.build(new JcaContentSignerBuilder("SHA256WithECDSA")
.setSecureRandom(secureRandom)
.build(keyPair.getPrivate()));
X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
byte[] salt = new byte[20];
new SecureRandom().nextBytes(salt);
KeyStore.PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(keyPair.getPrivate(),
new Certificate[] { cert });
keyStore.setEntry("server", privateKeyEntry,
new PasswordProtection("password".toCharArray(), "PBEWithHmacSHA512AndAES_256",
new PBEParameterSpec(salt, 100_000)));
keyStore.store(new FileOutputStream("/tmp/keystore.p12"), "changeit".toCharArray());
/*** RUN THIS AS JAVA 11 ***/
keyStore.load(new FileInputStream("/tmp/keystore.p12"), "changeit".toCharArray());
Key key = keyStore.getKey("server", "password".toCharArray());
System.out.println("Reloaded key: " + key);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Either do not use a custom PBE encryption scheme or recreate keystores from scratch when moving to Java 11.
FREQUENCY : always
|