从Java密钥库读取输出私钥

管理和保护私钥是许多应用程序的关键方面。Java密钥库(JKS) 是一种用于存储加密密钥和证书的流行格式。

在本教程中,我们将探讨从密钥库列出和导出私钥的两种方法:一种使用命令行,另一种使用 Java。

使用命令行 首先,我们使用JDK 提供的keytool实用程序列出密钥库中的所有条目,每个条目包括私钥、证书和别名:

keytool -list -keystore mykeystore.jks -storepass mypassword
在上面的命令中,mykeystore.jks是我们的密钥库文件名,mypassword是其密码。输出将类似于:

Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 2 entries
Alias name: privatekey1
Creation date: May 29, 2024
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Example, OU=Development, O=Company, L=City, ST=State, C=Country
...
Alias name: privatekey2
Creation date: May 29, 2024
...
接下来,我们将想要的私钥(-srcalias选项)从 JKS 文件导出到 PKCS12(.p12)文件:

keytool -importkeystore -srckeystore mykeystore.jks -destkeystore mykeystore.p12 -srcstoretype JKS -deststoretype PKCS12 
  -srcalias privatekey1 -srcstorepass mypassword -deststorepass mypassword

然后我们使用openssl 命令从 PKCS12 密钥库中提取私钥:

openssl pkcs12 -in mykeystore.p12 -nocerts -nodes -out privatekey.pem -passin pass:mypassword

这将以 PEM 格式提取私钥。-nocerts选项告诉openssl不要输出证书,-nodes防止私钥被加密。

最后,我们将PEM私钥转换为PKCS8格式:

openssl pkcs8 -in privatekey.pem -topk8 -nocrypt -out privatekey-pkcs8.pem
-topk8选项将密钥转换为 PKCS8 格式,-nocrypt选项确保密钥未加密。

最终结果如下:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCymad+US28aEBs
hj5nPJyiPotlyafiJSIKwbOu1rHcUYQukDxzRiKgp/j5dzneWhd7BUKDGLUNPL21
...
k7x6oTwzOTJsWsED69ZOC1E=
-----END PRIVATE KEY-----

使用 Java 我们还可以使用 Java 从密钥库中列出私钥:

try (InputStream is = new FileInputStream("mykeystore.jks")) {
    // Load the keystore
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    char[] passwordCharArr = "mypassword".toCharArray();
    keystore.load(is, passwordCharArr);
    for (String alias : Collections.list(keystore.aliases())) {
        if (keystore.isKeyEntry(alias)) {
            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry(
              alias, new KeyStore.PasswordProtection(passwordCharArr));
            PrivateKey privateKey = pkEntry.getPrivateKey();
            System.out.println("Alias: " + alias);
            System.out.println("-----BEGIN PRIVATE KEY-----");
            System.out.println(Base64.getMimeEncoder(64, "\n".getBytes())
              .encodeToString(privateKey.getEncoded()));
            System.out.println("-----END PRIVATE KEY-----");
        }
    }
}
让我们分解一下代码步骤:
  • 从文件加载密钥库。
  • 遍历密钥库中的所有别名。
  • 检查它是否是密钥条目(包括私钥)。
  • 以 PKCS8 格式检索并打印私钥。
此外,让我们使用try-with-resources,这样我们就不必担心手动关闭InputStream。