将 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
【讨论】:
是的,导出证书。但是,它不会导出关键信息... 这是我在几十个keytool
和 jboss
文档页面上搜索但没有成功的确切答案。谢谢!
这不会导出私钥信息
这会导出公钥证书
我尝试运行这个命令。它需要密码,输入密钥库密码: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。
>> "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' >> "myKeystore.pem"
的 -e 选项的引号
很遗憾,这只会导出证书,不会导出私钥
@user3217883 尝试使用单引号而不是双引号,例如,... | sed -e "/-*BEGIN [A-Z]*-*/,/-*END [A-Z]-*/!d" >> ...
【参考方案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 格式的主要内容,如果未能解决你的问题,请参考以下文章