Last week I managed to finish my first Java program (a commandline calculator: when you present it with 2 parameters they'll be used for all 4 major mathematic operations, otherwise it'll ask for the parameters) and this weekend I looked into deployment. I made a jarfile, then I made an "executable" jarfile and then I stumbled upon signing.
After I discovered the 'keytool' oddity (see other forum) I decided to rebuild my keystore. But since this would mean that I would also lose my keys I tried to use 'openssl' to look into the keystore, without any result. Then after reading up even more about this I discovered the jks and pkcs12 encoding differences and because it became quickly clear to me that Java supported both I tried to write a converter for it. It took me a few hours (I'm still a beginner when it comes to Java, slowly becoming more familiar with it) and here it is:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.*;
public class ConvertKeystore {
static public void main( String[] args ) {
try {
// define 2 keystore formats
KeyStore ks = KeyStore.getInstance("jks");
KeyStore nks = KeyStore.getInstance("pkcs12");
// Load the jks keystore and open the pkcs12 store
ks.load(new FileInputStream("/home/peter/.keystore"), "password".toCharA
rray());
nks.load(null, "changeit".toCharArray());
// Get the private key entry and store it in the new keystore
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry
("mykey", new KeyStore.PasswordProtection("password".toCharArray()));
nks.setEntry("newkey", pkEntry, new KeyStore.PasswordProtection("changeit
".toCharArray()));
// Store the new keystore
FileOutputStream fos = new FileOutputStream("/home/peter/new-keystore");
nks.store(fos, "changeit".toCharArray() );
fos.close();
} catch (Exception e) { System.out.println(e); }
}
} // End of class
This is all very basic ofcourse and still needs some work (as you can see it only converts 1 entry which also has to be explicitly named) but its sufficient for now. After this program has run you can convert the pkcs12 "new-store" file to a PEM keybag which will contain the private key as well as the certificate. You can do so using:
openssl pkcs12 -in new-keystore -out keybag.pem
And then you're left with a "keybag.pem" which is also in the usual PEM (ascii) format.
Now, as you can see I used "KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("mykey", new KeyStore.PasswordProtection("password".toCharArray()));" to 'filter' the result because "KeyStore.getEntry" returns a "KeyStore.Entry" while I needed a "PrivateKeyEntry". I've gone over the JDK documentation several times now but couldn't find anything to get a private keyentry directly so I finally wondered if I could "filter" it. I then noticed that the example in the KeyStore class also used this same method so I just went along with it.
Now I can't help wonder if I missed another possibility, has anyone else have another way to approach this ?