Privacy-Enhanced Mail (PEM) 本來是研究來給郵件加密的,現在主要成爲一種約定俗成的文件格式,用於存儲和發送加密密鑰,證書或其他數據。
簡單理解就是格式如下這種文件。
-----BEGIN XXX-----
BASE64
-----END XXX-----
JKS Keystore 轉化爲 PEM 的過程
在HTTPS SSL證書準備過程裏介紹過,我們生成了證書請求發給 CA 後,會收到一個 JKS Keystore 。
JKS Keystore 轉化爲 PEM 文件過程如下。
keytool -importkeystore -srckeystore appssl.jks -destkeystore appssl.jks.p12 -deststoretype pkcs12
keytool -deststoretype PKCS12 -keystore appssl.jks.p12 -list -storepass password
openssl pkcs12 -in appssl.jks.p12 -nokeys -clcerts -out client.crt
openssl pkcs12 -in appssl.jks.p12 -nokeys -cacerts -out ca.crt
cat client.crt ca.crt >server.crt
openssl pkcs12 -nocerts -nodes -in appssl.jks.p12 -out server.key
nokeys
表示不包含 Private Key, clcerts
輸出 Client Cert,cacerts
輸出 Root Cert 和 Intermediate Cert。
-nocerts -nodes
即不包含 Cert 和不加密。
實際上clcerts
和cacerts
兩個文件合起來和下面這句輸出一致。
openssl pkcs12 -in appssl.jks.p12 -nokeys -out server.crt
使用keytool
也可以直接從jks導出PEM,不過需要按alias逐個導出。
keytool -list -exportcert -keystore appssl.jks -alias 'appssl' -file server.crt -rfc
使用 openssl
導出的時候,還會添加如下Attributes。
Bag Attributes
friendlyName: app
localKeyID: 54 69 6D 65 20 41 45 48 49 45 44 42 44 40 42 49 41 47
subject=...app.dummy.com
issuer=...Entrust Certification Authority - L1M
而且 Root Cert 和 Intermediate Cert 會出現重複,因爲它們在 JKS Keystore 裏本來就是重複的。
JKS Keystore 裏有什麼
查看 JKS Keystore , 可以發現裏面包含3個實體,一個 PrivateKeyEntry 和兩個 trustedCertEntry。
但 PrivateKeyEntry 裏 Certificate chain length: 3
, 即包含了另外兩個 Cert,於是使用 Openssl轉化以後 Root Cert 和 Intermediate Cert 就出現了重複。
$ keytool -list -keystore appssl.jks -rfc
Keystore type: jks
Keystore provider: SUN
Your keystore contains 3 entries
Alias name: appssl
Creation date: Apr 18, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
-----BEGIN CERTIFICATE-----
BASE64
-----END CERTIFICATE-----
Certificate[2]:
-----BEGIN CERTIFICATE-----BASE64
-----END CERTIFICATE-----
Certificate[3]:
-----BEGIN CERTIFICATE-----BASE64
-----END CERTIFICATE-----
*******************************************
*******************************************
Alias name: cn=entrust certification authority - intermediate
Creation date: Apr 18, 2020
Entry type: trustedCertEntry
-----BEGIN CERTIFICATE-----
BASE64
-----END CERTIFICATE-----
*******************************************
*******************************************
Alias name: cn=entrust root certification authority
Creation date: Apr 18, 2020
Entry type: trustedCertEntry
-----BEGIN CERTIFICATE-----
BASE64
-----END CERTIFICATE-----
*******************************************
*******************************************
SSL 證書 PEM 文件裏要有什麼
特地做了下試驗。
使用 Openssl 導出的 PEM 當然是可以了,裏面包含了5個 PEM 。
刪掉重複的 Root Cert 和 Intermediate Cert 之後,表現也正常。
最後,只留下 Client Cert,瀏覽器裏表現正常,應用程序裏測試會出錯。
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我的簡單理解是,瀏覽器可以聯網查找認證鏈,應用程序不行。
相關規範
https://tools.ietf.org/html/rfc1421
https://tools.ietf.org/html/rfc7292
https://tools.ietf.org/html/rfc7468