开发者

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

I need to sign An开发者_如何学编程droid 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.


If you work with JDK 1.5 or below the keytool utility will not have the -importkeystore option (see JDK 1.5 keytool documentation) and the solution by MikeD will be available only by transferring the .pfx on a machine with a newer JDK (1.6 or above).

Another option in JDK 1.5 or below (if you have Oracle WebLogic product), is to follow the instructions from this Oracle document: Using PFX and PEM Certificate Formats with Keystores. It describes the conversion into .pem format, how to extract certificates information from this textual format, and import it into .jks format with java utils.ImportPrivateKey utility (this is an utility included with WebLogic product).


This is my solution for a Visual Studio/Xamarin environment.

Intended outcomes:

  • The PFX (foo.pfx in the examples) will be imported into JKS keystore (bar.keystore in the examples).
  • The keystore will be protected with a new password (shall be referred to as "signing password").
  • The keystore will contain a single key.
  • The single key will have an alias whose name matches that of the keystore (bar in the examples).
  • The single key will be protected with the signing password.
  • The Xamarin tooling will be able to use the keystore to easily sign apps.

Note that it is not necessary for the names and passwords to match, but this is common practice, as well as what the tooling expects.

  • See Understanding keystore, certificates and alias
  • See Signing the Android Application Package

keytool location: %JAVA_HOME%\bin, e.g.:

  • C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\bin
  • C:\Program Files (x86)\Java\jre1.8.0_331\bin

Steps:

  1. Obtain internally-signed PFX. PFX will have temporarily assigned password.
  2. Import JKS keystore from PFX; when prompted, supply signing password twice for destination keystore password, and supply temporarily assigned password for source keystore password.
    keytool -importkeystore -srckeystore foo.pfx -srcstoretype pkcs12 -destkeystore bar.keystore -deststoretype JKS
    
    Generated JKS keystore will have a single key alias "1" with same temporarily assigned password as PFX from step 1.
    • See https://stackoverflow.com/a/4714112/1399272 on How to convert .pfx file to keystore with private key?
    • See How to change a private key alias, "What keytool command do I use to change a private key alias?"
  3. Change key alias to match keystore name; when prompted, supply signing password for keystore password, and temporarily assigned password for key password.
    keytool -changealias -alias 1 -destalias bar -keystore bar.keystore
    
    • See https://stackoverflow.com/a/5707518/1399272 on How to change the alias of a key within a keystore?
  4. Change key password to signing password; when prompted, supply signing password for keystore password, temporarily assigned password for old key password, and signing password twice for new key password.
    keytool -keypasswd -keystore bar.keystore -alias bar
    
    • See https://stackoverflow.com/a/49771772/1399272 on Android keystore password change
  5. Ensure finished keystore is located at the following path, or similar per your installation:
    %LOCALAPPDATA%\Xamarin\Mono for Android\Keystore\bar\bar.keystore
    

Verify content:

  1. View contents of original PFX; when prompted, supply temporarily assigned password for keystore password.
    keytool -list -v -keystore foo.pfx -storetype pkcs12
    
  2. View contents of generated keystore; when prompted, supply signing password for keystore password.
    keytool -list -v -keystore bar.keystore
    
  3. Compare output from steps 1 and 2 (e.g. save to text file and perform file diff). Content should be identical (i.e. certificate chains, fingerprints, etc.; header and footer text will differ).

You should now be able to see and use the imported keystore when using the Ad-Hoc distribution option in Visual Studio. Provide the signing password when prompted.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜