How to convert .pfx file to keystore with private key?

I need to sign Android application (.apk).
I have .pfx file. I converted it to .cer file via Internet Explorer and then converted .cer to .keystore using keytool. Then I've tried to sign .apk with jarsigner but it says that .keystore doesn't content a private key.

What I'm doing wrong?


Using JDK 1.6 or later

It has been pointed out by Justin in the comments below that keytool alone is capable of doing this using the following command (although only in JDK 1.6 and later):

keytool -importkeystore -srckeystore mypfxfile.pfx -srcstoretype pkcs12 
-destkeystore clientcert.jks -deststoretype JKS

Using JDK 1.5 or below

OpenSSL can do it all. This answer on JGuru is the best method that I've found so far.

Firstly make sure that you have OpenSSL installed. Many operating systems already have it installed as I found with Mac OS X.

The following two commands convert the pfx file to a format that can be opened as a Java PKCS12 key store:

openssl pkcs12 -in mypfxfile.pfx -out mypemfile.pem
openssl pkcs12 -export -in mypemfile.pem -out mykeystore.p12 -name "MyCert"

NOTE that the name provided in the second command is the alias of your key in the new key store.

You can verify the contents of the key store using the Java keytool utility with the following command:

keytool -v -list -keystore mykeystore.p12 -storetype pkcs12

Finally if you need to you can convert this to a JKS key store by importing the key store created above into a new key store:

keytool -importkeystore -srckeystore mykeystore.p12 -destkeystore clientcert.jks -srcstoretype pkcs12 -deststoretype JKS

I found this page which tells you how to import a PFX to JKS (Java Key Store):

keytool -importkeystore -srckeystore PFX_P12_FILE_NAME -srcstoretype pkcs12 -srcstorepass PFX_P12_FILE -srcalias SOURCE_ALIAS -destkeystore KEYSTORE_FILE -deststoretype jks -deststorepass PASSWORD -destalias ALIAS_NAME

jarsigner can use your pfx file as the keystore for signing your jar. Be sure that your pfx file has the private key and the cert chain when you export it. There is no need to convert to other formats. The trick is to obtain the Alias of your pfx file:

 keytool -list -storetype pkcs12 -keystore your_pfx_file -v | grep Alias

Once you have your alias, signing is easy

jarsigner.exe -storetype pkcs12 -keystore pfx_file jar_file "your alias"

The above two commands will prompt you for the password you specified at pfx export. If you want to have your password hang out in clear text use the -storepass switch before the -keystore switch

Once signed, admire your work:

jarsigner.exe -verify -verbose -certs  yourjarfile

Justin(above) is accurate. However, keep in mind that depending on who you get the certificate from (intermediate CA, root CA involved or not) or how the pfx is created/exported, sometimes they could be missing the certificate chain. After Import, You would have a certificate of PrivateKeyEntry type, but with a chain of length of 1.

To fix this, there are several options. The easier option in my mind is to import and export the pfx file in IE(choosing the option of Including all the certificates in the chain). The import and export process of certificates in IE should be very easy and well documented elsewhere.

Once exported, import the keystore as Justin pointed above. Now, you would have a keystore with certificate of type PrivateKeyEntry and with a certificate chain length of more than 1.

Certain .Net based Web service clients error out(unable to establish trust relationship), if you don't do the above.


Your PFX file should contain the private key within it. Export the private key and certificate directly from your PFX file (e.g. using OpenSSL) and import them into your Java keystore.

Edit

Further information:

  • Download OpenSSL for Windows here.
  • Export private key: openssl pkcs12 -in filename.pfx -nocerts -out key.pem
  • Export certificate: openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
  • Import private key and certificate into Java keystore using keytool.