Extract a Secret Key from a Java Keystore
Yesterday, I was trying to pull a shared secret (a SecretKeyEntry
not a PrivateKeyEntry
) out of a Java keystore.
I'd created it quite some time ago and annoyingly didn't have a copy of the secret stored anywhere. What I did have, however, was the keystorepass
and the keypass
, so wanted to pull the key out.
This was achievable using the below Java class:
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.KeyStoreException;
import javax.crypto.SecretKey;
public class OutputSecretKey {
public static void main(String[] args) throws Exception {
final String fileName = args[0];
final String alias = args[1];
final char[] storepass = args[2].toCharArray();
final char[] keypass = args[3].toCharArray();
KeyStore ks = KeyStore.getInstance("JCEKS");
try (FileInputStream fis = new FileInputStream(fileName)) {
ks.load(fis, storepass);
SecretKey secretKey = (SecretKey) ks.getKey(alias, keypass);
String secretAsHex = new BigInteger(1, secretKey.getEncoded()).toString(16);
System.out.println(hexToAscii(secretAsHex));
}
}
/* https://www.baeldung.com/java-convert-hex-to-ascii */
private static String hexToAscii(String hexStr) {
StringBuilder output = new StringBuilder("");
for (int i = 0; i < hexStr.length(); i += 2) {
String str = hexStr.substring(i, i + 2);
output.append((char) Integer.parseInt(str, 16));
}
return output.toString();
}
}
This can then be run as follows:
$ javac OutputSecretKey.java
$ java OutputSecretKey keystore.jceks alias thisisthekeystorepass thekeyhasthispassword
supersecretpassword
Note that this code has been adapted from How to display Java keystore SecretKeyEntry from command line and Convert Hex to ASCII in Java.