将 Java 密钥库转换为 PEM 格式

Posted

技术标签:

【中文标题】将 Java 密钥库转换为 PEM 格式【英文标题】:Converting a Java Keystore into PEM Format 【发布时间】:2010-10-13 18:24:39 【问题描述】:

我正在尝试使用 keytool 和 openssl 应用程序将 Java 密钥库文件转换为 PEM 文件。但是我找不到进行转换的好方法。有任何想法吗?

我没有将密钥库直接转换为 PEM,而是尝试先创建一个 PKCS12 文件,然后再转换为相关的 PEM 文件和密钥库。但我无法使用它们建立连接。 (请注意,我只需要一个 PEM 文件和一个 Keystore 文件来实现安全连接。没有像“从 java keystore 文件开始”这样的限制。:) 所以我的情况可以从其他格式开始)

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

【问题讨论】:

【参考方案1】:

很简单,至少用jdk6...

bash$ keytool -keystore foo.jks -genkeypair -alias foo \ -dname 'CN=foo.example.com,L=墨尔本,ST=维多利亚,C=AU' 输入密钥库密码: 重新输入新的密码: 输入密钥密码 (如果与密钥库密码相同,则返回): bash$ keytool -keystore foo.jks -exportcert -alias foo | \ openssl x509 -inform der -text 输入密钥库密码:asdasd 证书: 数据: 版本:3 (0x2) 序列号:1237334757 (0x49c03ae5) 签名算法:dsaWithSHA1 发行人:C=AU,ST=维多利亚,L=墨尔本,CN=foo.example.com 有效性 不早于:格林威治标准时间 2009 年 3 月 18 日 00:05:57 不晚于:格林威治标准时间 2009 年 6 月 16 日 00:05:57 主题:C=AU,ST=维多利亚,L=墨尔本,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=维多利亚,L=墨尔本,CN=foo.example.com 有效性 不早于:格林威治标准时间 2009 年 3 月 18 日 00:05:57 不晚于:格林威治标准时间 2009 年 6 月 16 日 00:05:57 主题:C=AU,ST=维多利亚,L=墨尔本,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

【讨论】:

此方法不支持受信任的证书:这是对 PKS12 格式的限制,我相信请参阅:java.sun.com/javase/6/docs/technotes/guides/security/jsse/…(有关 java.security.KeyStoreException 的部分:不支持 TrustedCertEntry) 我有一个较旧的 JKS 文件。我无法使用上述方法导出。我终于能够通过将 keytool arg '-destkeypass' 设置为虚拟值来做到这一点。 'keytool' 甚至会提示警告说它忽略了 destkeypass 值?没有其他技术会起作用。使用提示不起作用,只能从命令行参数起作用。一定是 PKCS12 导出中的错误,有人可以评论吗? "openssl pkcs12 -in foo.p12 -out foo.pem" 抛出以下错误输入导入密码:MAC 验证 OK 输出密钥和证书时出错 139848775526048:错误:06065064:数字信封例程:EVP_DecryptFinal_ex:坏解密:evp_enc.c:539:139848775526048:错误:23077074:PKCS12例程:PKCS12_pbe_crypt:PKCS12 cipherfinal错误:p12_decr.c:104:139848775526048:错误:2306A075:PKCS12例程:PKCS12_item_decrypt_d2i:PKCS12 PBE隐窝错误:p12_decr.c: 130.有什么办法解决这个问题? 对其他人的警告,keytool 命令由于某种原因需要一段时间才能完成,我不得不等待 30 秒直到导出完成 @UdaraS.SLiyanage:看看凯西对解决方案的回答【参考方案2】:

在使用 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,参数的值无关紧要。

【讨论】:

原因可以在这里找到:herongyang.com/PKI/… destkeypass 顺便说一句 我赞成这条评论,但它值得拥有自己的帖子。在这里很难找到。【参考方案3】:

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

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

【讨论】:

是的,导出证书。但是,它不会导出关键信息... 这是我在几十个 keytooljboss 文档页面上搜索但没有成功的确切答案。谢谢! 这不会导出私钥信息 这会导出公钥证书 我尝试运行这个命令。它需要密码,输入密钥库密码:keytool错误:java.io.IOException:密钥库被篡改,或密码不正确。我使用了密码作为(密码),但它抛出了同样的错误【参考方案4】:

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 的直接转换”。我说的对吗? 您只需要编写代码到 Java 1.4 - 从 Java 5 开始,keytool 和 openssl 可以结合起来执行从 JKS -> PKCS#12 的两阶段转换-> PEM。但是,编写自己的密钥工具是从 JKS -> PEM 执行 DIRECT CONVERSION 的唯一方法。 我认为它是从 JDK 6 开始的。但是,是的,现在支持 PKCS #12 导入。【参考方案5】:

将 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>

【讨论】:

【参考方案6】:

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

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

解释:

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

【讨论】:

bash: !d": 找不到事件 @user3217883 您可以尝试类似sed "s/^\-*BEGIN [A-Z]*\-*$//g;s/^\-*END [A-Z]*\-*$//g" 的方法(使用 gnu sed),但如果您的密钥库中有多个证书,我不确定这是否足够 如果您收到 bash: !d": event not found :对于 bash,感叹号是使用命令的快捷键。要使用此答案,您需要使用撇号代替用作 sed keytool -list -rfc -keystore "myKeystore.jks" | sed -e '/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d' &gt;&gt; "myKeystore.pem" 的 -e 选项的引号 很遗憾,这只会导出证书,不会导出私钥 @user3217883 尝试使用单引号而不是双引号,例如,... | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" &gt;&gt; ...【参考方案7】:

首先将密钥库从 JKS 转储到 PKCS12

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

将新的 pkcs12 文件转储到 pem 中

    openssl pkcs12 -in middle.p12 -nodes -out middle.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 块的通用名称(仅限)openssl base64 -d【参考方案8】:

我找到了一个非常有趣的解决方案:

http://www.swview.org/node/191

然后,我将公钥/私钥对分成两个文件 private.key publi.pem 并且它可以工作!

【讨论】:

【参考方案9】:

如果您没有安装 openssl 并且您正在寻找快速解决方案,可以使用名为 portcle 的软件,该软件非常有用且易于下载。

缺点是据我所知没有命令行。 但从 GUI 中,导出 PEM 私钥非常简单:

    打开你的 JKS 密钥库 右键单击您的私钥条目并选择导出

    选择私钥和证书以及 PEM 格式

【讨论】:

【参考方案10】:

好吧,OpenSSL should do it handily 来自 #12 文件:

openssl pkcs12 -in pkcs-12-certificate-file -out pem-certificate-file
openssl pkcs12 -in pkcs-12-certificate-and-key-file -out pem-certificate-and-key-file

也许有关错误/失败的更多详细信息?

【讨论】:

【参考方案11】:

试试 Keystore Explorer http://keystore-explorer.org/

KeyStore Explorer 是 Java 命令行实用程序 keytool 和 jarsigner 的开源 GUI 替代品。它也支持 openssl/pkcs12。

【讨论】:

【参考方案12】:

首先创建密钥库文件为

C:\Program Files\android\Android Studio\jre\bin>keytool -keystore androidkey.jks -genkeypair -alias androidkey

输入密钥库密码: 重新输入新密码: 你的名字和姓氏是什么? 未知:名字姓氏 您的组织单位的名称是什么? 未知:移动开发 您的组织名称是什么? 未知:您的公司名称 您所在城市或地区的名称是什么? 您所在的州或省的名称是什么? 本机的两个字母的国家/地区代码是什么? 未知:IN //按回车

现在它会要求确认

CN=FirstName LastName、OU=Mobile Development、O=your company name、L=CityName、ST=StateName、C=IN 是否正确? [否]:是的

输入密钥密码 (如果与密钥库密码相同,则返回):如果您想要相同的密码,请按 Enter

key已经生成,现在你可以使用以下命令简单地获取pem文件

C:\Program Files\Android\Android Studio\jre\bin>keytool -export -rfc -alias androidkey -file android_certificate.pem -keystore androidkey.jks 输入密钥库密码: 证书存储在文件中

【讨论】:

这不会给the 2011 answer by sanghaviss添加任何有用的东西,它只输出证书而不是私钥【参考方案13】:

我只留下以下两个命令来完成这项工作

# openssl pkcs12 -info -nodes -in /srv/apache-tomcat-8.5.72/conf/cert.jks -nokeys 2>&1| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > server.crt
Enter Import Password:
# openssl pkcs12 -info -nodes -in /srv/apache-tomcat-8.5.72/conf/cert.jks -nocerts 2>&1| sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > server.key
Enter Import Password:

【讨论】:

【参考方案14】:

打开终端并转到 jks 文件位置 并写下这个>>>> keytool -export -rfc -alias key0 -file android_certificate.pem -keystore androidkey.jks

【讨论】:

【参考方案15】:

将 Java 密钥库转换为 PEM 格式

最准确的答案一定是这是不可能的。

Java 密钥库只是加密密钥证书的存储工具,而 PEM 只是 X.509 证书的文件格式。

【讨论】:

这是完全错误的。 PEM 文件广泛用于证书、CRL、(PKCS10) CSR 和私钥,而不太广泛用于 PKCS7/CMS 消息(包括 p7b/p7c 证书和/或 CRL 捆绑包)、裸公钥、参数以及更罕见的东西比如 OpenSSL 保存的会话块和 OCSP 消息。对于官方标准,请参阅RFC7468。 @dave_thompson_085 - 没错,PEM 不仅仅与 X.509 证书有关。但是我的观点是,您可以将 anything 存储在 Java Keystore 中,只要它符合 docs.oracle.com/javase/7/docs/api/java/security/… 的(空)接口 - 而 PEM 似乎绑定到某些 Crypto 标准(而不是到任意 base64 编码)。 包括 KeyStore 在内的所有 JCA API(有意)都非常广泛,但这些 API 背后的实际实现不需要如此。对于重要示例,JKS 和 PKCS12 仅支持存在证书工厂的证书类型,并且唯一存在的证书工厂是 X.509。 PEM(RFC1421)“可打印编码”可以应用于任何二进制数据,尽管它主要用于 ASN.1 数据(主要是 DER,一些 BER,例如 PKCS7/CMS),这仍然是一个非常广泛的集合。 (几乎同时定义的非常相似的 MIME base64 编码用于各种数据。)

以上是关于将 Java 密钥库转换为 PEM 格式的主要内容,如果未能解决你的问题,请参考以下文章

将 CA 签名的 JKS 密钥库转换为 PEM

将证书从 pem 转换为 jks

如何将 ECDSA 密钥转换为 PEM 格式

将 pem 密钥转换为 ssh-rsa 格式

sh 将密钥从二进制(由生成密钥生成)转换为pem格式。适用于私钥和公钥

将 ssh-dss 密钥转换为 .pem?