Search code examples
javarsabouncycastlepkcs#12

How to create private key from pkcs12 in java


I need to create PrivateKey from privateKeyContent which is in pkcs12 format. Below code doesn't work for it.

   KeyFactory kf = KeyFactory.getInstance("RSA");
   PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent));
   PrivateKey privateRsaKey = kf.generatePrivate(keySpecPKCS8);

It gives me this error.

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : version mismatch: (supported:     00, parsed:     03
    at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:251)
    at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)

How to do it correctly in java?


Solution

  • PKCS12 format is a container that may have multiple keys and certificates. PKCS8 file always has one key. In your code sample, you apply PKCS8EncodedKeySpec to PKCS12 input, this is obviously not going to work because of this. You need to switch from Key-level APIs to KeyStore APIs.

    You can read PKCS12 container like this:

    InputStream keyFile = ...; //input stream to key file
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(keyFile, "<filePassword>".toCharArray());
    

    and extract a specific key from the loaded storage:

    String keyAlias = "1"; // all existing aliases can be obtained by ks.aliases()
    Key key = ks.getKey(keyAlias, "<keyPassword>".toCharArray());
    

    This is how you can read a key from this specific demo .p12 file:

    InputStream keyFile = ...; // load file as an IS
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(keyFile, null);
    Key key = ks.getKey("1", "test".toCharArray());