How do I list and export a private key from a keystore?
A nice clean example for listing all of the aliases in a key store can be found here
// Load input stream into keystore
keystore.load(is, password.toCharArray());
// List the aliases
Enumeration enum = keystore.aliases();
for (; enum.hasMoreElements(); ) {
String alias = (String)enum.nextElement();
// Does alias refer to a private key?
boolean b = keystore.isKeyEntry(alias);
// Does alias refer to a trusted certificate?
b = keystore.isCertificateEntry(alias);
}
The exporting of private keys came up on the Sun forums a couple of months ago, and u:turingcompleter came up with a DumpPrivateKey class to stitch into your app.
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
import sun.misc.BASE64Encoder;
public class DumpPrivateKey {
/**
* Provides the missing functionality of keytool
* that Apache needs for SSLCertificateKeyFile.
*
* @param args <ul>
* <li> [0] Keystore filename.
* <li> [1] Keystore password.
* <li> [2] alias
* </ul>
*/
static public void main(String[] args)
throws Exception {
if(args.length < 3) {
throw new IllegalArgumentException("expected args: Keystore filename, Keystore password, alias, <key password: default same tha
n keystore");
}
final String keystoreName = args[0];
final String keystorePassword = args[1];
final String alias = args[2];
final String keyPassword = getKeyPassword(args,keystorePassword);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(new FileInputStream(keystoreName), keystorePassword.toCharArray());
Key key = ks.getKey(alias, keyPassword.toCharArray());
String b64 = new BASE64Encoder().encode(key.getEncoded());
System.out.println("-----BEGIN PRIVATE KEY-----");
System.out.println(b64);
System.out.println("-----END PRIVATE KEY-----");
}
private static String getKeyPassword(final String[] args, final String keystorePassword)
{
String keyPassword = keystorePassword; // default case
if(args.length == 4) {
keyPassword = args[3];
}
return keyPassword;
}
}
Note: this use Sun package, which is a "bad thing".
If you can download apache commons code, here is a version which will compile without warning:
javac -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey.java
and will give the same result:
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
//import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64;
public class DumpPrivateKey {
/**
* Provides the missing functionality of keytool
* that Apache needs for SSLCertificateKeyFile.
*
* @param args <ul>
* <li> [0] Keystore filename.
* <li> [1] Keystore password.
* <li> [2] alias
* </ul>
*/
static public void main(String[] args)
throws Exception {
if(args.length < 3) {
throw new IllegalArgumentException("expected args: Keystore filename, Keystore password, alias, <key password: default same tha
n keystore");
}
final String keystoreName = args[0];
final String keystorePassword = args[1];
final String alias = args[2];
final String keyPassword = getKeyPassword(args,keystorePassword);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(new FileInputStream(keystoreName), keystorePassword.toCharArray());
Key key = ks.getKey(alias, keyPassword.toCharArray());
//String b64 = new BASE64Encoder().encode(key.getEncoded());
String b64 = new String(Base64.encodeBase64(key.getEncoded(),true));
System.out.println("-----BEGIN PRIVATE KEY-----");
System.out.println(b64);
System.out.println("-----END PRIVATE KEY-----");
}
private static String getKeyPassword(final String[] args, final String keystorePassword)
{
String keyPassword = keystorePassword; // default case
if(args.length == 4) {
keyPassword = args[3];
}
return keyPassword;
}
}
You can use it like so:
java -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey $HOME/.keystore changeit tomcat
If you don't need to do it programatically, but just want to manage your keys, then I've used IBM's free KeyMan tool for a long time now. Very nice for exporting a private key to a PFX file (then you can easily use OpenSSL to manipulate it, extract it, change pwds, etc).
http://www.alphaworks.ibm.com/tech/keyman/download
Select your keystore, select the private key entry, then File->Save to a pkcs12 file (*.pfx, typically). You can then view the contents with:
$ openssl pkcs12 -in mykeyfile.pfx -info
Here is the answer, found on http://www.memofy.com/memofy/show/000863e71fa863e7008545a7bfe138/How_to_export_private_key_from_SUN_keystore
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.security.*;
import java.security.cert.Certificate;
public class ExportPrivateKey {
private File keystoreFile;
private String keyStoreType;
private char[] password;
private char[] keypassword;
private String alias;
private File exportedFile;
public static KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
Key key = keystore.getKey(alias, password);
if (key instanceof PrivateKey) {
Certificate cert = keystore.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
return new KeyPair(publicKey, (PrivateKey) key);
}
return null;
}
public void export() throws Exception {
KeyStore keystore = KeyStore.getInstance(keyStoreType);
BASE64Encoder encoder = new BASE64Encoder();
keystore.load(new FileInputStream(keystoreFile), password);
KeyPair keyPair = getPrivateKey(keystore, alias, keypassword);
PrivateKey privateKey = keyPair.getPrivate();
String encoded = encoder.encode(privateKey.getEncoded());
FileWriter fw = new FileWriter(exportedFile);
fw.write("-----BEGIN PRIVATE KEY-----\n");
fw.write(encoded);
fw.write("\n");
fw.write("-----END PRIVATE KEY-----");
fw.close();
}
public static void main(String args[]) throws Exception {
ExportPrivateKey export = new ExportPrivateKey();
export.keystoreFile = new File(args[0]);
export.keyStoreType = args[1];
export.password = args[2].toCharArray();
export.keypassword = args[3].toCharArray();
export.alias = args[4];
export.exportedFile = new File(args[5]);
export.export();
}
}
Use as follows: java ExportPrivateKey keystoreFile keyStoreType password keypassword alias