Blog·Tanky WooABOUTRSS

JKS to PEM

29 Dec 2014

JKS(Java KeyStore)是Java的一个证书仓库, 包括授权证书和公钥证书等.

$ file tankywoo.jks
tankywoo.jks: Java KeyStore

JDK 提供了一个工具 keytool 用于管理keystore.

安装JDK:

# Gentoo
$ sudo emerge -av virtual/jdk

# Ubuntu 两个都行
# sudo apt-get install openjdk-6-jdk    # 1.6
# sudo apt-get install openjdk-7-jdk    # 1.7 

(如果安装JRE, 则emerge -av virtual/jre)

现提供了一个JKS证书文件和证书的密码,需要转成PEM文件给Nginx SSL配置.

先通过keytool导出成PKCS12格式(.p12后缀):

$ keytool -importkeystore -srckeystore tankywoo.jks -destkeystore tankywoo.p12 -srcstoretype jks -deststoretype pkcs12
Enter destination keystore password:
Re-enter new password:
Enter source keystore password:
Entry for alias foo successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled

指定源(jks)文件和目标(pkcs)文件的文件名和类型.

执行时输入设置给pkcs12证书的密码, 以及jks证书的密码.

再通过openssl将pkcs12文件导出成pem格式文件.

# 生成key 加密的pem证书
$ openssl pkcs12 -in tankywoo.p12 -out tankywoo.pem
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

# 生成key 非加密的pem证书
$ openssl pkcs12 -nodes -in tankywoo.p12 -out tankywoo.pem
Enter Import Password:
MAC verified OK

也可以分开导出:

导出key:

# 生成加密的key
$ openssl pkcs12 -in tankywoo.p12  -nocerts -out server.key
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

# 生成非加密的key
$ openssl pkcs12 -in tankywoo.p12 -nocerts -nodes -out server.key
Enter Import Password:
MAC verified OK

导出server证书:

$ openssl pkcs12 -in tankywoo.p12  -nokeys -clcerts -out server.crt
Enter Import Password:
MAC verified OK

导出ca证书:

$ openssl pkcs12 -in tankywoo.p12  -nokeys -cacerts -out ca.crt
Enter Import Password:
MAC verified OK

2015-03-11 补充:

今天有一个jks证书, 导出为p12时报错:

$ keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12 -srcstoretype jks -deststoretype pkcs12

Enter destination keystore password:
Re-enter new password:
Enter source keystore password:
Entry for alias keystore successfully imported.
Problem importing entry for alias intermediate2: java.security.KeyStoreException: TrustedCertEntry not supported.
Entry for alias intermediate2 not imported.
Do you want to quit the import process? [no]:  n
Problem importing entry for alias intermediate1: java.security.KeyStoreException: TrustedCertEntry not supported.
Entry for alias intermediate1 not imported.
Do you want to quit the import process? [no]:  n
Import command completed:  1 entries successfully imported, 2 entries failed or cancelled

生成的p12只能导出server.crt和ca.crt, 无法导出server.key

查看jks证书内容:

$ keytool -list -v -keystore keystore.jks

看到有两个trustedCertEntry

Alias name: intermediate1
Creation date: Apr 30, 2014
Entry type: trustedCertEntry
...

Alias name: intermediate2
Creation date: Apr 30, 2014
Entry type: trustedCertEntry
...

这个讨论里提到了原因: ref 1

具体也可以看手册

java.security.KeyStoreException: TrustedCertEntry not supported
Problem: Attempt to store trusted certificates in PKCS12 keystore throws java.security.KeyStoreException: TrustedCertEntry not supported.

Cause 1: We do not support storing trusted certificates in pkcs12 keystore. PKCS12 is mainly used to deliver private keys with the associated cert chains. It does not have any notion of "trusted" certificates. Note that in terms of interoperability, other pkcs12 vendors have the same restriction. Browsers such as Mozilla and Internet Explorer do not accept a pkcs12 file with only trusted certs.

Solution 1: Use JKS (or JCEKS) keystore for storing trusted certificates.

但是把Google搜了一圈, 也没发现解决方法, 囧.

后来问老大, 刚好他几年前的一篇博客有方法 从 JKS keystore 中迁移证书到 Apache

具体可参考这篇博客Exporting the Private Key From a JKS Keystore, 这是一个java写的工具, 下载zip包直接使用 ExportPrivateKey.zip

调用方式:

java -jar ExportPrivateKey.zip {keystore_path} JKS {keystore_password} {alias} {target_file}

alias可以通过上面的keytool -list看到.

用此命令生成了server.key, 和之前生成的server.crt, ca.crt合并就可以了


参考: