如何列出/导出密钥库中的私钥?
如何列出并从密钥库中导出私钥?
来自Example Depot的一部分代码,用于列出密钥存储区中的所有别名:
// Load input stream into keystore keystore.load(is, password.toCharArray()); // List the aliases Enumeration aliases = keystore.aliases(); for (; aliases.hasMoreElements(); ) { String alias = (String)aliases.nextElement(); // Does alias refer to a private key? boolean b = keystore.isKeyEntry(alias); // Does alias refer to a trusted certificate? b = keystore.isCertificateEntry(alias); }
私人密钥的出口在几个月前出现在Sun论坛上 ,而u:turingcompleter想出了一个DumpPrivateKey类来绑定到你的应用程序。
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; } }
注意:这个使用Sun软件包, 这是一件“坏事” 。
如果你可以下载apache的commons代码 ,这里是一个没有警告的编译版本:
javac -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey.java
并会给出相同的结果:
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; } }
你可以这样使用它:
java -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey $HOME/.keystore changeit tomcat
您可以使用Java6和OpenSSL从密钥库中提取私钥。 这完全取决于Java和OpenSSL支持PKCS#12格式的密钥库的事实。 要进行提取,首先使用keytool
转换为标准格式。 确保对这两个文件(私钥密码,而不是密钥库密码)使用相同的密码,否则第二步中会出现奇怪的错误。
keytool -importkeystore -srckeystore keystore.jks \ -destkeystore intermediate.p12 -deststoretype PKCS12
接下来,使用OpenSSL对PEM进行提取:
openssl pkcs12 -in intermediate.p12 -out extracted.pem -nodes
您应该能够轻松处理该PEM文件; 它是纯文本,其中包含一个编码的未encryption私钥和证书(以非常明显的格式)。
当你这样做时,注意保持文件的安全。 他们包含秘密证件。 如果你没有正确的保护他们,没有什么会提醒你的。 保护他们的最简单的方法是在一个没有任何其他用户访问权限的目录中完成所有这些操作。 永远不要把你的密码放在命令行或环境variables中; 其他用户很容易抓住。
如果您不需要以编程方式执行此操作,但只想pipe理您的密钥,那么现在我已经使用IBM免费的KeyMan工具了。 非常好的将私钥导出到PFX文件(然后你可以很容易地使用OpenSSL来处理它,提取它,改变pwds等)。
select您的密钥库,select私钥条目,然后select文件 – >保存到pkcs12文件(通常是* .pfx)。 您可以通过以下方式查看内容:
$ openssl pkcs12 -in mykeyfile.pfx -info
在Groovy中,这是上面代码的一个较短版本。 也有内置的base64编码:
import java.security.Key import java.security.KeyStore if (args.length < 3) throw new IllegalArgumentException('Expected args: <Keystore file> <Keystore format> <Keystore password> <alias> <key password>') def keystoreName = args[0] def keystoreFormat = args[1] def keystorePassword = args[2] def alias = args[3] def keyPassword = args[4] def keystore = KeyStore.getInstance(keystoreFormat) keystore.load(new FileInputStream(keystoreName), keystorePassword.toCharArray()) def key = keystore.getKey(alias, keyPassword.toCharArray()) println "-----BEGIN PRIVATE KEY-----" println key.getEncoded().encodeBase64() println "-----END PRIVATE KEY-----"
对于android开发,将eclipse ADT中创build的keystore转换为SignApk.jar中使用的公钥和私钥:
导出私钥:
keytool.exe -importkeystore -srcstoretype JKS -srckeystore my-release-key.keystore -deststoretype PKCS12 -destkeystore keys.pk12.der openssl.exe pkcs12 -in keys.pk12.der -nodes -out private.rsa.pem
编辑private.rsa.pem并将“—– BEGIN PRIVATE KEY —–”改为“—– END PRIVATE KEY —–”段落,然后:
openssl.exe base64 -d -in private.rsa.pem -out private.rsa.der
导出公钥:
keytool.exe -exportcert -keystore my-release-key.keystore -storepass <KEYSTORE_PASSWORD> -alias alias_name -file public.x509.der
签名apk:
java -jar SignApk.jar public.x509.der private.rsa.der input.apk output.apk
这个问题出现在stackexchange安全性上,其中一个build议是使用Keystore explorer
刚刚尝试过,它工作得很好,我强烈推荐它。
首先,要小心! 所有的安全取决于…呃私钥的 隐私 。 Keytool没有内置密钥输出以避免意外披露这些敏感资料,因此您可能需要考虑一些额外的安全措施,以保护您的导出密钥。
下面是一些简单的代码,它提供了OpenSSL可以使用的未encryption的PKCS#8 PrivateKeyInfo(请参阅其pkcs8实用程序的-nocrypt
选项):
KeyStore keys = ... char[] password = ... Enumeration<String> aliases = keys.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); if (!keys.isKeyEntry(alias)) continue; Key key = keys.getKey(alias, password); if ((key instanceof PrivateKey) && "PKCS#8".equals(key.getFormat())) { /* Most PrivateKeys use this format, but check for safety. */ try (FileOutputStream os = new FileOutputStream(alias + ".key")) { os.write(key.getEncoded()); os.flush(); } } }
如果您需要其他格式,则可以使用KeyFactory为不同types的键获取透明密钥规范。 然后你可以得到一个RSA私钥的私有指数,并以你想要的格式输出。 这将成为后续问题的一个好主题。
另一个很棒的工具是KeyStore Explorer: http : //keystore-explorer.sourceforge.net/
JXplorer是另一个不太常规的,但可以说更简单的方法。 虽然这个工具被devise为浏览LDAP目录,但它有一个易于使用的GUI来操作密钥库。 GUI上的一个这样的function可以从JKS密钥库中导出私钥。