将Java密钥库转换为PEM格式

159

我正在尝试使用keytoolopenssl应用程序将Java密钥库文件转换为PEM文件。然而,我找不到一个理想的方法来进行转换。有什么想法吗?

与其直接将密钥库转换为PEM,我尝试先创建一个PKCS12文件,然后将其转换为相关的PEM文件和密钥库。然而,我无法使用它们建立连接。

(请注意,我需要一个PEM文件和一个密钥库文件来实现安全连接。没有像“从Java密钥库文件开始”的限制。因此,在我的情况下,从其他格式开始是可以接受的)

但是,从jks直接转换为pem的方法更可取。

16个回答

251
这很简单,至少使用jdk6...
bash$ keytool -keystore foo.jks -genkeypair -alias foo \ -dname 'CN=foo.example.com,L=Melbourne,ST=Victoria,C=AU' 输入密钥库密码: 重新输入新密码: 输入密钥密码 (如果与密钥库密码相同,请按回车): bash$ keytool -keystore foo.jks -exportcert -alias foo | \ openssl x509 -inform der -text 输入密钥库密码:asdasd 证书: 数据: 版本:3(0x2) 序列号:1237334757(0x49c03ae5) 签名算法:dsaWithSHA1 颁发者:C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com 有效期: 之前:Mar 18 00:05:57 2009 GMT 之后:Jun 16 00:05:57 2009 GMT 主题:C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com 主题公钥信息: 公钥算法:dsaEncryption DSA公钥: 公钥: 00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14: 7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:
bash$ keytool -importkeystore -srckeystore foo.jks \ -destkeystore foo.p12 \ -srcstoretype jks \ -deststoretype pkcs12 输入目标密钥库密码: 重新输入新密码: 输入源密钥库密码: 别名foo的条目导入成功。 导入命令完成:成功导入1个条目,0个条目失败或取消
bash$ openssl pkcs12 -in foo.p12 -out foo.pem 输入导入密码: MAC验证成功 输入PEM密码短语: 验证 - 输入PEM密码短语:
bash$ openssl x509 -text -in foo.pem 证书: 数据: 版本:3(0x2) 序列号:1237334757(0x49c03ae5) 签名算法:dsaWithSHA1 颁发者:C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com 有效期: 之前:Mar 18 00:05:57 2009 GMT 之后:Jun 16 00:05:57 2009 GMT 主题:C=AU, ST=Victoria, L=Melbourne, CN=foo.example.com 主题公钥信息: 公钥算法:dsaEncryption DSA公钥: 公钥: 00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14: 7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:
bash$ openssl dsa -text -in foo.pem 读取DSA密钥 输入PEM密码短语: 私钥:(1024位) 私钥: 00:8f:b1:af:55:63:92:7c:d2:0f:e6:f3:a2:f5:ff: 1a:7a:fe:8c:39:dd 公钥: 00:e2:66:5c:e0:2e:da:e0:6b:a6:aa:97:64:59:14: 7e:a6:2e:5a:45:f9:2f:b5:2d:f4:34:27:e6:53:c7:
你最终得到的是:
  • foo.jks - Java格式的密钥库。
  • foo.p12 - PKCS#12格式的密钥库。
  • foo.pem - 密钥库中的所有密钥和证书,以PEM格式。

(如果需要,最后一个文件可以拆分为密钥和证书。)


命令摘要 - 创建JKS密钥库:

keytool -keystore foo.jks -genkeypair -alias foo \
    -dname 'CN=foo.example.com,L=Melbourne,ST=Victoria,C=AU'

命令摘要 - 将JKS密钥库转换为PKCS#12密钥库,然后转换为PEM文件:
keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcstoretype jks \
   -deststoretype pkcs12

openssl pkcs12 -in foo.p12 -out foo.pem

如果您的JKS密钥库中有多个证书,并且您只想导出与其中一个别名关联的证书和密钥,您可以使用以下变体:
keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcalias foo \
   -srcstoretype jks \
   -deststoretype pkcs12

openssl pkcs12 -in foo.p12 -out foo.pem

命令摘要 - 比较 JKS 密钥库和 PEM 文件:
keytool -keystore foo.jks -exportcert -alias foo | \
   openssl x509 -inform der -text

openssl x509 -text -in foo.pem

openssl dsa -text -in foo.pem

12
此方法不支持受信任证书:我认为这是PKS12格式的限制,请参考:http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallProbs (关于java.security.KeyStoreException: TrustedCertEntry not supported的部分)。 - andygavin
2
我有一个旧的JKS文件。我无法使用上述方法导出。我最终通过将keytool参数“-destkeypass”设置为虚拟值来实现。'keytool'甚至提示警告说它正在忽略destkeypass值?没有其他技术可行。使用提示无效,只有从命令行参数才有效。一定是PKCS12导出中的错误,有人能评论一下吗? - cmcginty
4
"openssl pkcs12 -in foo.p12 -out foo.pem" 报错如下: 输入导入密码: MAC 验证通过 输出密钥和证书时出错 139848775526048:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539: 139848775526048:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:104: 139848775526048:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:130. 解决方法是什么? - Udara S.S Liyanage
1
作为对其他人的警告,由于某些原因,keytool命令需要一段时间才能完成,我不得不等待30秒直到导出完成。 - Nicolas Mommaerts
1
@UdaraS.SLiyanage:看看Casey的答案,那是解决方案。 - Nicolas Mommaerts
显示剩余3条评论

30

当我使用StoBor的命令时,openssl一直出错:

MAC verified OK
Error outputting keys and certificates
139940235364168:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:535:
139940235364168:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:97:
139940235364168:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:123:

由于某种原因,只有这种命令样式适用于我的JKS文件

keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcstoretype jks \
   -srcalias mykey \
   -deststoretype pkcs12 \
   -destkeypass DUMMY123

关键是设置destkeypass,参数的值并不重要。


7
推理过程可以在此处找到:http://www.herongyang.com/PKI/Intermediate-CA-OpenSSL-pkcs12-Decrypt-Error.html 顺便提一下,destkeypass 确实很重要。 - Nicolas Mommaerts
我点赞了这条评论,但它应该有自己的帖子。在这里找到它很困难。 - Richie Rich

21

使用keytool从jks文件直接转换为pem文件

keytool -exportcert -alias selfsigned -keypass password -keystore test-user.jks -rfc -file test-user.pem

10
是的,这将导出证书。但是,它不会导出密钥信息... - Stobor
这正是我在数十个“keytool”和“jboss”文档页面上搜索而没有成功找到的确切简单答案。谢谢! - kratenko
19
这不会导出私钥信息。 - James
1
这将导出公钥证书。 - asami
这将导出 public.pem 证书。如何找到 private.pem? - Devendra Singraul
显示剩余2条评论

15

将JKS文件转换为PEM和KEY格式(.crt & .key)的简化指南:

keytool -importkeystore -srckeystore <Source-Java-Key-Store-File> -destkeystore <Destination-Pkcs12-File> -srcstoretype jks -deststoretype pkcs12 -destkeypass <Destination-Key-Password>

openssl pkcs12 -in <Destination-Pkcs12-File> -out <Destination-Pem-File>

openssl x509 -outform der -in <Destination-Pem-File> -out <Destination-Crt-File>

openssl rsa -in <Destination-Pem-File> -out <Destination-Key-File>

15

keytool 命令无法从密钥库中导出私钥,您需要编写一些 Java 代码来完成此操作。打开密钥库,获取所需的密钥,并将其保存到 PKCS #8 格式的文件中。也要保存相关证书。

KeyStore ks = KeyStore.getInstance("jks");
/* Load the key store. */
...
char[] password = ...;
/* Save the private key. */
FileOutputStream kos = new FileOutputStream("tmpkey.der");
Key pvt = ks.getKey("your_alias", password);
kos.write(pvt.getEncoded());
kos.flush();
kos.close();
/* Save the certificate. */
FileOutputStream cos = new FileOutputStream("tmpcert.der");
Certificate pub = ks.getCertificate("your_alias");
cos.write(pub.getEncoded());
cos.flush();
cos.close();

使用OpenSSL工具将这些以二进制格式存储的文件转换为PEM格式。

openssl pkcs8 -inform der -nocrypt < tmpkey.der > tmpkey.pem
openssl x509 -inform der < tmpcert.der > tmpcert.pem

谢谢Erickson。结论是“我们无法仅使用keytool和openssl实用程序直接从JKS转换为PEM”。我说得对吗? - Chathuranga Chandrasekara
4
您只需要编写Java 1.4版本的代码 - 自Java 5起,可以结合使用keytool和openssl执行两阶段转换从JKS -> PKCS#12 -> PEM。但是,编写自己的密钥工具是从JKS -> PEM进行直接转换的唯一方法。 - Stobor
我认为它是从JDK 6开始支持的。但是,是的,现在支持PKCS#12导入。 - erickson

6

将JKS KeyStore转换为单个PEM文件可以使用以下命令轻松完成:

keytool -list -rfc -keystore "myKeystore.jks" | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" >> "myKeystore.pem"

解释:

  1. keytool -list -rfc -keystore "myKeystore.jks" 以PEM格式列出 'myKeyStore.jks' KeyStore 中的所有内容。但它也打印了额外的信息。
  2. | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" 过滤掉我们不需要的所有内容。我们只剩下KeyStore中所有内容的PEM。
  3. >> "myKeystore.pem" 将PEM写入文件 'myKeyStore.pem'。

4
bash: !d": 事件未找到 - user3217883
1
@user3217883 你可以尝试使用类似于 sed "s/^\-*BEGIN [A-Z]*\-*$//g;s/^\-*END [A-Z]*\-*$//g" 的命令(使用gnu sed),但如果密钥库中有多个证书,则我不确定这是否足够。 - Idriss Neumann
如果你在使用bash时遇到了“bash: !d”: event not found”的错误提示:在bash中,感叹号是一个快捷键,用于使用命令。为了使用这个答案,你需要在选项中使用单引号代替双引号,例如sed的-e选项:keytool -list -rfc -keystore 'myKeystore.jks' | sed -e '/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d' >> 'myKeystore.pem' - B.Adler
很遗憾,这只导出证书,而不是私钥。 - Maddin
@user3217883 请尝试使用单引号而不是双引号,例如:... | sed -e '/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d' >> ... - kevinarpe

4

首先将密钥库从JKS转换到PKCS12格式

1. keytool -importkeystore -srckeystore ~/.android/debug.keystore -destkeystore intermediate.p12 -srcstoretype JKS -deststoretype PKCS12

将新的pkcs12文件转换为pem格式

  1. openssl pkcs12 -in intermediate.p12 -nodes -out intermediate.rsa.pem

您应该已经拥有pem格式的证书和私钥。将它们分开。 将“BEGIN CERTIFICATE”和“END CERTIFICATE”之间的部分放入cert.x509.pem中 将“BEGIN RSA PRIVATE KEY”和“END RSA PRIVATE KEY”之间的部分放入private.rsa.pem中 将私钥转换为signapk所需的pk8格式

3. openssl pkcs8 -topk8 -outform DER -in private.rsa.pem -inform PEM -out private.pk8 -nocrypt


在 OpenSSL 1.0.0 版本(发布于 2010 年)及其以上版本中,“openssl pkcs12” 应该已经以 PKCS8 格式输出私钥 - 但是输出的是 PEM 格式,因此如果需要 DER 格式,则需要使用“openssl pkcs8 -topk8 -outform der” 进行特定转换,或者对单独的 PEM 块 (only) 进行通用转换,即“openssl base64 -d”。 - dave_thompson_085

3
如果您没有安装openssl并且正在寻找快速解决方案,那么有一款名为portcle的软件非常实用且下载量很小。
缺点是据我所知没有命令行。但是从GUI界面,导出PEM私钥非常直观:
  1. 打开您的JKS密钥库
  2. 右键单击您的私钥条目并选择导出
  3. 选择私钥和证书以及PEM格式

    Export PEM private key from JKS with Portcle


3
假设您的密钥库文件名为 abcd.jks,它位于 C:\Data 目录下,执行以下命令在该目录下的 cmd 窗口中:
keytool -export -rfc -keystore C:\Data\abcd.jks -alias abcd -file C:\Data\abcd.pem

在被提示时输入密码,然后您将在指定位置获得转换后的格式


2

打开您的终端并转到jks文件位置,然后输入以下命令:

keytool -export -rfc -alias key0 -file android_certificate.pem -keystore androidkey.jks

非常直接明了。 - Kipkemoi Derek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接