156

I am trying to convert from a Java keystore file into a PEM file using keytool and openssl applicactions. But I could not find a good way to do the conversion. Any ideas?

Instead of converting the keystore directly into PEM I tried to create a PKCS12 file first and then convert into relevant PEM file and Keystore. But I could not establish a connection using them. (Note that I just need a PEM file and a Keystore file to implement a secured connection. There is no restriction like "Start from a java keystore file". :) So starting from other formats is acceptable with my case)

But a direct conversion method from jks to pem is preferable.

Randall
  • 2,859
  • 1
  • 21
  • 24
Chathuranga Chandrasekara
  • 20,548
  • 30
  • 97
  • 138

16 Answers16

249

It's pretty straightforward, using jdk6 at least...

bash$ keytool -keystore foo.jks -genkeypair -alias foo \
        -dname 'CN=foo.example.com,L=Melbourne,ST=Victoria,C=AU'
Enter keystore password:  
Re-enter new password: 
Enter key password for 
        (RETURN if same as keystore password):  
bash$ keytool -keystore foo.jks -exportcert -alias foo | \
       openssl x509 -inform der -text
Enter keystore password:  asdasd
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1237334757 (0x49c03ae5)
        Signature Algorithm: dsaWithSHA1
        Issuer: C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com
        Validity
            Not Before: Mar 18 00:05:57 2009 GMT
            Not After : Jun 16 00:05:57 2009 GMT
        Subject: C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com
        Subject Public Key Info:
            Public Key Algorithm: dsaEncryption
            DSA Public Key:
                pub: 
                    00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14:
                    7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:
 

bash$ keytool -importkeystore -srckeystore foo.jks \
       -destkeystore foo.p12 \
       -srcstoretype jks \
       -deststoretype pkcs12
Enter destination keystore password:  
Re-enter new password: 
Enter source keystore password:  
Entry for alias foo successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled

bash$ openssl pkcs12 -in foo.p12 -out foo.pem
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

bash$ openssl x509 -text -in foo.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1237334757 (0x49c03ae5)
        Signature Algorithm: dsaWithSHA1
        Issuer: C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com
        Validity
            Not Before: Mar 18 00:05:57 2009 GMT
            Not After : Jun 16 00:05:57 2009 GMT
        Subject: C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com
        Subject Public Key Info:
            Public Key Algorithm: dsaEncryption
            DSA Public Key:
                pub: 
                    00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14:
                    7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:
 

bash$ openssl dsa -text -in foo.pem
read DSA key
Enter PEM pass phrase:
Private-Key: (1024 bit)
priv:
    00:8f:b1:af:55:63:92:7c:d2:0f:e6:f3:a2:f5:ff:
    1a:7a:fe:8c:39:dd
pub: 
    00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14:
    7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:



You end up with:

  • foo.jks - keystore in java format.
  • foo.p12 - keystore in PKCS#12 format.
  • foo.pem - all keys and certs from keystore, in PEM format.

(This last file can be split up into keys and certificates if you like.)


Command summary - to create JKS keystore:

keytool -keystore foo.jks -genkeypair -alias foo \
    -dname 'CN=foo.example.com,L=Melbourne,ST=Victoria,C=AU'

Command summary - to convert JKS keystore into PKCS#12 keystore, then into PEM file:

keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcstoretype jks \
   -deststoretype pkcs12

openssl pkcs12 -in foo.p12 -out foo.pem

if you have more than one certificate in your JKS keystore, and you want to only export the certificate and key associated with one of the aliases, you can use the following variation:

keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcalias foo \
   -srcstoretype jks \
   -deststoretype pkcs12

openssl pkcs12 -in foo.p12 -out foo.pem

Command summary - to compare JKS keystore to PEM file:

keytool -keystore foo.jks -exportcert -alias foo | \
   openssl x509 -inform der -text

openssl x509 -text -in foo.pem

openssl dsa -text -in foo.pem
Stobor
  • 44,246
  • 6
  • 66
  • 69
  • 12
    Trusted certificates are not supported in this method: this is a restriction of the PKS12 format I believe see: http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallProbs (section on java.security.KeyStoreException: TrustedCertEntry not supported) – andygavin Sep 11 '09 at 12:10
  • @andygavin: Indeed; this is true. While the PKCS format can hold arbitrarily many certificates, it does not have a field to indicate whether the certificate is trusted or not. However, the question was about how to end up with a PEM (PKCS#7) file, which also doesn't have this trust information, so it's not an issue of the process... – Stobor Sep 14 '09 at 14:10
  • 2
    I have an older JKS file. I could not export using the method above. I finally was able to do it by setting keytool arg '-destkeypass' to a dummy value. 'keytool' even prompts a warning saying it is ignoring destkeypass value? No other technique would work. Using the prompts did not work, only works from the command line argument. Must be a bug in the PKCS12 export, can anyone comment? – cmcginty Nov 17 '12 at 02:39
  • 4
    "openssl pkcs12 -in foo.p12 -out foo.pem" throws the following error Enter Import Password: MAC verified OK Error outputting keys and certificates 139848775526048:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539: 139848775526048:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:104: 139848775526048:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:130. What is the solution for this? – Udara S.S Liyanage Mar 18 '13 at 07:39
  • 1
    a warning for other people, the keytool command takes a while to complete for some reason, I had to wait 30 seconds until the export was done – Nicolas Mommaerts Jun 19 '13 at 07:47
  • 1
    @UdaraS.SLiyanage: look at Casey's answer for the solution – Nicolas Mommaerts Jun 19 '13 at 07:57
  • I got errors (keytool error: java.io.IOException: DER input, Integer tag error) until I deleted the destination keystore file before running the command. Make sure that the destination keystore file does not exist before running the command. – jnnnnn Sep 21 '15 at 05:11
  • If you're using git-bash on windows, you may want to prefix `openssl ...` with `winpty openssl ...` – solstice333 May 11 '21 at 19:05
30

I kept getting errors from openssl when using StoBor's command:

MAC verified OK
Error outputting keys and certificates
139940235364168:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:535:
139940235364168:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:97:
139940235364168:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:123:

For some reason, only this style of command would work for my JKS file

keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcstoretype jks \
   -srcalias mykey \
   -deststoretype pkcs12 \
   -destkeypass DUMMY123

The key was setting destkeypass, the value of the argument did not matter.

Nicolas Mommaerts
  • 3,207
  • 4
  • 35
  • 55
cmcginty
  • 113,384
  • 42
  • 163
  • 163
21

Direct conversion from jks to pem file using the keytool

keytool -exportcert -alias selfsigned -keypass password -keystore test-user.jks -rfc -file test-user.pem
sra
  • 23,820
  • 7
  • 55
  • 89
sanghaviss
  • 235
  • 2
  • 2
15

The keytool command will not allow you to export the private key from a key store. You have to write some Java code to do this. Open the key store, get the key you need, and save it to a file in PKCS #8 format. Save the associated certificate too.

KeyStore ks = KeyStore.getInstance("jks");
/* Load the key store. */
...
char[] password = ...;
/* Save the private key. */
FileOutputStream kos = new FileOutputStream("tmpkey.der");
Key pvt = ks.getKey("your_alias", password);
kos.write(pvt.getEncoded());
kos.flush();
kos.close();
/* Save the certificate. */
FileOutputStream cos = new FileOutputStream("tmpcert.der");
Certificate pub = ks.getCertificate("your_alias");
cos.write(pub.getEncoded());
cos.flush();
cos.close();

Use OpenSSL utilities to convert these files (which are in binary format) to PEM format.

openssl pkcs8 -inform der -nocrypt < tmpkey.der > tmpkey.pem
openssl x509 -inform der < tmpcert.der > tmpcert.pem
erickson
  • 265,237
  • 58
  • 395
  • 493
  • Thanks erickson.. The conclusion is "We can't perform a direct conversion from JKS to PEM by just using keytool and openssl utilities". Am I correct? – Chathuranga Chandrasekara Mar 17 '09 at 05:51
  • 4
    You only __need__ to write code up to Java 1.4 - from Java 5 onwards, keytool and openssl can be combined to perform a two stage conversion from JKS -> PKCS#12 -> PEM. However, writing your own key tool is the only way to perform __DIRECT CONVERSION__ from JKS -> PEM. – Stobor Oct 04 '10 at 00:54
  • I think it's from JDK 6 onward. But yes, a PKCS #12 import is now supported. – erickson Oct 04 '10 at 06:11
14

Simplified instructions to converts a JKS file to PEM and KEY format (.crt & .key):

keytool -importkeystore -srckeystore <Source-Java-Key-Store-File> -destkeystore <Destination-Pkcs12-File> -srcstoretype jks -deststoretype pkcs12 -destkeypass <Destination-Key-Password>

openssl pkcs12 -in <Destination-Pkcs12-File> -out <Destination-Pem-File>

openssl x509 -outform der -in <Destination-Pem-File> -out <Destination-Crt-File>

openssl rsa -in <Destination-Pem-File> -out <Destination-Key-File>
asami
  • 773
  • 6
  • 12
6

Converting a JKS KeyStore to a single PEM file can easily be accomplished using the following command:

keytool -list -rfc -keystore "myKeystore.jks" | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" >> "myKeystore.pem"

Explanation:

  1. keytool -list -rfc -keystore "myKeystore.jks" lists everything in the 'myKeyStore.jks' KeyStore in PEM format. However, it also prints extra information.
  2. | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" filters out everything we don't need. We are left with only the PEMs of everything in the KeyStore.
  3. >> "myKeystore.pem" write the PEMs to the file 'myKeyStore.pem'.
Mark Lagendijk
  • 6,247
  • 2
  • 36
  • 24
  • 4
    bash: !d": event not found – user3217883 May 17 '16 at 21:32
  • 1
    @user3217883 You could try something like `sed "s/^\-*BEGIN [A-Z]*\-*$//g;s/^\-*END [A-Z]*\-*$//g"` instead (with gnu sed) but i'm not sure that's enough if there are more than one cert in your keystore – Idriss Neumann May 02 '17 at 18:34
  • if you're getting `bash: !d": event not found` : for bash an exclamation mark is a short key to use a command. To use this answer you need to use apostrophes in place of the quotes for the option used as -e for sed `keytool -list -rfc -keystore "myKeystore.jks" | sed -e '/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d' >> "myKeystore.pem"` – B.Adler Nov 13 '19 at 19:24
  • Unfortunately, this only exports the certificate, not the private key – Maddin Nov 20 '19 at 15:12
  • @user3217883 Try single quotes instead of double quotes, e.g., `... | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" >> ...` – kevinarpe May 25 '21 at 08:07
4

First dump the keystore from JKS to PKCS12

1. keytool -importkeystore -srckeystore ~/.android/debug.keystore -destkeystore intermediate.p12 -srcstoretype JKS -deststoretype PKCS12

Dump the new pkcs12 file into pem

  1. openssl pkcs12 -in intermediate.p12 -nodes -out intermediate.rsa.pem

You should have both the cert and private key in pem format. Split them up. Put the part between “BEGIN CERTIFICATE” and “END CERTIFICATE” into cert.x509.pem Put the part between “BEGIN RSA PRIVATE KEY” and “END RSA PRIVATE KEY” into private.rsa.pem Convert the private key into pk8 format as expected by signapk

3. openssl pkcs8 -topk8 -outform DER -in private.rsa.pem -inform PEM -out private.pk8 -nocrypt

nkalra0123
  • 2,281
  • 16
  • 17
  • In OpenSSL versions 1.0.0 (released 2010) and up, `openssl pkcs12` should already output the privatekey in PKCS8 format -- but PEM, so if you need DER you do need either the specific conversion by `openssl pkcs8 -topk8 -outform der` or the generic one for a single isolated PEM block (only) `openssl base64 -d` – dave_thompson_085 Apr 01 '21 at 04:19
3

In case you don't have openssl installed and you are looking for a quick solution, there is software called portcle which is very useful and small to download.

The disadvantage is that there is no command line as far as I know. But from the GUI, it is pretty straight forward to export a PEM private key:

  1. Open you JKS key store
  2. Right click over your private key entry and select export
  3. Select Private Key and certificates and PEM format

    Export PEM private key from JKS with Portcle

Marcio Jasinski
  • 1,439
  • 16
  • 22
3

Suppose your keystore file is abcd.jks and its present at C:\Data,

try this in cmd window, at the location where the file is present:

keytool -export -rfc -keystore C:\Data\abcd.jks -alias abcd -file C:\Data\abcd.pem

Give password next, when prompted, and you will get the converted format at the location specified

2

open your terminal and going to jks file location and write this >>>> keytool -export -rfc -alias key0 -file android_certificate.pem -keystore androidkey.jks

Ahmed Mohamed
  • 301
  • 1
  • 12
1

Try Keystore Explorer http://keystore-explorer.org/

KeyStore Explorer is an open source GUI replacement for the Java command-line utilities keytool and jarsigner. It does openssl/pkcs12 as well.

Johnnyboy
  • 19
  • 1
1

first create keystore file as

C:\Program Files\Android\Android Studio\jre\bin>keytool -keystore androidkey.jks -genkeypair -alias androidkey

Enter keystore password:
Re-enter new password:
What is your first and last name? Unknown: FirstName LastName
What is the name of your organizational unit? Unknown: Mobile Development
What is the name of your organization? Unknown: your company name
What is the name of your City or Locality? What is the name of your State or Province?
What is the two-letter country code for this unit? Unknown: IN //press enter

Now it will ask to confirm

Is CN=FirstName LastName, OU=Mobile Development, O=your company name, L=CityName, ST=StateName, C=IN correct? [no]: yes

Enter key password for (RETURN if same as keystore password): press enter if you want same password

key has been generated, now you can simply get pem file using following command

C:\Program Files\Android\Android Studio\jre\bin>keytool -export -rfc -alias androidkey -file android_certificate.pem -keystore androidkey.jks
Enter keystore password:
Certificate stored in file

Ankit Dubey
  • 1,000
  • 1
  • 8
  • 12
  • This doesn't add anything useful to [the 2011 answer by sanghaviss](https://stackoverflow.com/a/6076689/2868801) and it outputs only the cert not the private key – dave_thompson_085 Apr 01 '21 at 04:16
1

Well, OpenSSL should do it handily from a #12 file:

openssl pkcs12 -in pkcs-12-certificate-file -out pem-certificate-file
openssl pkcs12 -in pkcs-12-certificate-and-key-file -out pem-certificate-and-key-file

Maybe more details on what the error/failure is?

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
0

I just leave following two commands here that does the job

# openssl pkcs12 -info -nodes -in /srv/apache-tomcat-8.5.72/conf/cert.jks -nokeys 2>&1| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > server.crt
Enter Import Password:
# openssl pkcs12 -info -nodes -in /srv/apache-tomcat-8.5.72/conf/cert.jks -nocerts 2>&1| sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > server.key
Enter Import Password:
Chris
  • 939
  • 2
  • 11
  • 22
0

keytool -exportcert -alias selfsigned -keypass password -keystore key-store.jks -rfc -file test-user.pem

The command will prompt to enter keyStore password - Enter the keystore password

password - The key password. key-store - The keystore file (jks or keystore)

it will be easy when you have key and keystore passwords the same.

-2

Converting a Java Keystore into PEM Format

The most precise answer of all must be that this is NOT possible.

A Java keystore is merely a storage facility for cryptographic keys and certificates while PEM is a file format for X.509 certificates only.

wh81752
  • 869
  • 9
  • 16
  • This is quite wrong. PEM files are widely used for certificates, CRLs, (PKCS10) CSRs, and private keys, and less widely for PKCS7/CMS messages (including p7b/p7c cert and/or CRL bundles), bare public keys, parameters, and more rarely things like OpenSSL saved-session blocks and OCSP messages. For the _officially standard_ ones see [RFC7468](https://tools.ietf.org/html/rfc7468). – dave_thompson_085 Apr 01 '21 at 04:28
  • @dave_thompson_085 - True, that PEM is not only about X.509 certificates. However my point has been that you can store *anything* within a Java Keystore as long as it complies with the (empty) interface of https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.Entry.html - while PEM appears to be bound to some Crypto standards (and not to an arbitrary base64 encoding). – wh81752 Apr 20 '21 at 11:03
  • All JCA APIs including KeyStore are (intentionally) very broad, but actual implementations behind those APIs need not be. For important examples JKS and PKCS12 support only certificate types for which a certificatefactory exists, and the only certificatefactory that exists is X.509. PEM (RFC1421) 'printable encoding' can be applied to any binary data, although it is mostly used for ASN.1 data (mostly DER, some BER e.g. PKCS7/CMS) which is still a very wide set. (The very similar MIME base64 encoding, defined almost simultaneously, is used for all kinds of data.) – dave_thompson_085 Apr 20 '21 at 22:22