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

Java Keystore fails to load PKCS12/PFX certificates created in WindowsServer2016

XMLWordPrintable

    • b20
    • x86_64
    • windows

        A DESCRIPTION OF THE PROBLEM :
        I am trying to parse a PKCS12 certificate into a x509 and a private key using the Java Keystore:

        final KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
        keystore.load(pkcs12Certificate, password.toCharArray());
        final Enumeration<String> aliases = keystore.aliases();
        final String alias = aliases.nextElement();
        final PrivateKey key = (PrivateKey) keystore.getKey(alias,
                    password.toCharArray());
        final X509Certificate publicCertificate = (X509Certificate) keystore
                    .getCertificate(alias);
        return create(clientId, key, publicCertificate);`

        This has worked well for certificates built by windows-server-2012. We have updated VMs to windows-server-2016, which has broken this code with the following error:

        Exception in thread "main" java.io.IOException: Integrity check failed:
        java.security.UnrecoverableKeyException: Failed PKCS12 integrity checking
        at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2146)
        at java.base/java.security.KeyStore.load(KeyStore.java:1479)
        at com.company.AsymmetricKeyCredential.create(AsymmetricKeyCredential.java:164)
        at com.company.Main.main(Main.java:29)
        Caused by: java.security.UnrecoverableKeyException: Failed PKCS12 integrity checking
        at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2142)
        ... 3 more`
        After some digging around it seems that windows-server-2016 has changed the way they format PKCS12 and PFX certificates. Specifically:

        Pre-RS1, PKCS7 EncryptedData was used for the CertBag; in RS1, that was switched to PKCS7 Data. There are the multiple options of AUthSafe contents in a CertBag:

              AuthenticatedSafe ::= SEQUENCE OF ContentInfo
           -- Data if unencrypted
           -- EncryptedData if password-encrypted
           -- EnvelopedData if public key-encrypted


        I am trying to parse a PKCS12 certificate into a x509 and a private key using the Java Keystore:

        final KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
        keystore.load(pkcs12Certificate, password.toCharArray());
        final Enumeration<String> aliases = keystore.aliases();
        final String alias = aliases.nextElement();
        final PrivateKey key = (PrivateKey) keystore.getKey(alias,
                    password.toCharArray());
        final X509Certificate publicCertificate = (X509Certificate) keystore
                    .getCertificate(alias);
        return create(clientId, key, publicCertificate);`
        This has worked well for certificates built by windows-server-2012. We have updated VMs to windows-server-2016, which has broken this code with the following error:

        Exception in thread "main" java.io.IOException: Integrity check failed:
        java.security.UnrecoverableKeyException: Failed PKCS12 integrity checking
        at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2146)
        at java.base/java.security.KeyStore.load(KeyStore.java:1479)
        at com.company.AsymmetricKeyCredential.create(AsymmetricKeyCredential.java:164)
        at com.company.Main.main(Main.java:29)
        Caused by: java.security.UnrecoverableKeyException: Failed PKCS12 integrity checking
        at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2142)
        ... 3 more`
        After some digging around it seems that windows-server-2016 has changed the way they format PKCS12 and PFX certificates. Specifically:

        Pre-RS1, PKCS7 EncryptedData was used for the CertBag; in RS1, that was switched to PKCS7 Data. There are the multiple options of AUthSafe contents in a CertBag:

              AuthenticatedSafe ::= SEQUENCE OF ContentInfo
           -- Data if unencrypted
           -- EncryptedData if password-encrypted
           -- EnvelopedData if public key-encrypted

        It seems like this switch might be causing the Java Keystore to fail, but I'm not sure how to fix it. I can parse the certificate with open ssl, so I know its not an issue with the certificate itself.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Create a PKCS12 certificate with Windows Server 2016, and try to load it into the Java keystore.

        final KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
        keystore.load(pkcs12Certificate, password.toCharArray());
        final Enumeration<String> aliases = keystore.aliases();
        final String alias = aliases.nextElement();
        final PrivateKey key = (PrivateKey) keystore.getKey(alias,
                    password.toCharArray());
        final X509Certificate publicCertificate = (X509Certificate) keystore
                    .getCertificate(alias);

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expecting the certificate to be loaded.
        ACTUAL -
        Exception in thread "main" java.io.IOException: Integrity check failed:
        java.security.UnrecoverableKeyException: Failed PKCS12 integrity checking

        FREQUENCY : always


          1. broken_split.p12
            3 kB
          2. JI9053509.java
            1 kB
          3. split.p12
            3 kB

              weijun Weijun Wang
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: