views:

12763

answers:

3

I am trying to convert into 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 idea?

Instead of converting the kaystore into PEM I tried to create a PKCS12 file first and then convert into relevant PEM file and Keystore. But I could not establish 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 direct conversion method from jks to pem is more preferred.

+1  A: 

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
+6  A: 

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
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
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
I think it's from JDK 6 onward. But yes, a PKCS #12 import is now supported.
erickson
+6  A: 

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
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
@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
that should read "... while the PKCS#12 format..."
Stobor