1. 概述
管理私钥是许多应用安全的关键环节。Java 密钥库(JKS)是存储加密密钥和证书的常用格式。本文将介绍两种从密钥库中列出和导出私钥的方法:命令行操作和 Java 编程实现。
2. 使用命令行操作
首先通过 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 格式:
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
✅ 关键参数:
-nocerts
:不输出证书-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-----
3. 使用 Java 实现
通过 Java 代码读取密钥库中的私钥更灵活,核心步骤如下:
try (InputStream is = new FileInputStream("mykeystore.jks")) {
// 加载密钥库
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();
// 输出私钥(PKCS8格式)
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-----");
}
}
}
✅ 代码要点:
- 使用
try-with-resources
自动关闭输入流- 通过
isKeyEntry()
过滤私钥条目- 用
Base64.getMimeEncoder()
格式化输出
4. 总结
对比两种方法:
- 命令行方案:简单粗暴,适合快速操作
- Java 方案:更灵活,适合程序化处理密钥库内容
❌ 踩坑提醒:实际操作时注意密钥库密码的安全性,避免硬编码在代码中
完整示例代码可在 GitHub 获取。