

本文部分摘錄於 SSL Shopper,這里提供了大量有價值的信息。
一、證書標准
1、X.509
這是一種證書標准,主要定義了證書中應該包含哪些內容。其詳情可以參考 RFC5280
,SSL 使用的就是這種證書標准。
同樣的 X.509 證書,可能有不同的編碼格式。最常見的就是 PEM 和 DER 兩種格式。但是有個比較誤導人的地方,這兩種格式的文件,擴展名不一定就是 .pem
或 .der
,還有其他一些常見格式。它們除了編碼格式可能不同之外,內容也有差別。但是大多數都能相互轉換編碼格式。
2、作為文件形式存在的證書一般有這幾種格式:
- 帶有私鑰的證書(P12)
由 Public Key Cryptography Standards #12,PKCS#12 標准定義,包含了公鑰和私鑰的二進制格式的證書形式,以 pfx 作為證書文件后綴名。 - 二進制編碼的證書(DER)
證書中沒有私鑰,DER 編碼二進制格式的證書文件,以.cer
作為證書文件后綴名。 - Base64 編碼的證書(PEM)
證書中沒有私鑰,Base64 編碼格式的證書文件,也是以.cer
作為證書文件后綴名。
由定義可以看出,只有 pfx/p12 格式的數字證書是包含有私鑰的,cer 格式的數字證書里面只有公鑰沒有私鑰。
不同的平台和設備,需要不同格式的 SSL 證書。例如:
.pfx
- Windows 平台使用.crt, .cer
- Apache Server 使用
注意:區分
PEM .pem
和DER .cer
唯一的辦法,就是使用文本編輯器打開,查看BEGIN/END
聲明。
二、主要格式
1、PEM 格式
PEM(Privacy Enhanced Mail),OpenSSL 使用 PEM 格式來存放各種信息,它是 OpenSSL 默認采用的信息存放方式,是 CA(Certificate Authorities)頒發證書最常用的格式。包含 —–BEGIN CERTIFICATE—–
和 —–END CERTIFICATE--
聲明。
多個 PEM 證書甚至於 Private Key 可以被包含到一個文件中,一個挨一個往下排布。但是大多數平台(如:Apache),希望證書和私鑰分別存放到不同的文件中。
文件一般包含如下信息:
-
內容類型:
表明本文件存放的是什么信息內容,它的形式為“——-BEGIN XXXX ——”,與結尾的“——END XXXX——”對應。 -
頭信息:
表明數據是如果被處理后存放,OpenSSL 中用的最多的是加密信息,比如加密算法以及初始化向量 iv。 -
信息體:
為 BASE64 編碼的數據。可以包括所有私鑰(RSA 和 DSA)、公鑰(RSA 和 DSA)和 (x509) 證書。它存儲用 Base64 編碼的 DER 格式數據,用 ascii 報頭包圍,因此適合系統之間的文本模式傳輸。
PEM 格式文件特點:
- Base64 編碼的 ASCII 文件
- 具備諸如
.pem, .crt, .cer, .key
這樣的擴展名 - Apache 和類似的服務器使用 PEM 格式的證書
查看 PEM 格式證書的信息:
$ openssl x509 -in certificate.pem -text -noout
使用 PEM 格式 存儲的證書:
--BEGIN CERTIFICATE-- MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx ...... 1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU= --END CERTIFICATE--
使用 PEM 格式存儲的私鑰:
--BEGIN RSA PRIVATE KEY-- MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx ……… 1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU= --END RSA PRIVATE KEY--
使用 PEM 格式存儲的證書請求文件:
--BEGIN CERTIFICATE REQUEST-- MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx ……… 1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU= --END CERTIFICATE REQUEST--
2、DER 格式
辨別編碼規則 DER(Distinguished Encoding Rules)是 ASCII PEM 格式證書的二進制形式。所有類型的證書和私鑰都可以被編碼為 DER 格式。
它是大多數瀏覽器的缺省格式,並按 ASN1 DER 格式存儲。它是無報頭的。
PEM 是用文本報頭包圍的 DER。
- 二進制文件
- 擴展名為
.cer
和.der
- DER 被典型地於 Java 平台
查看 DER 格式證書的信息:
$ openssl x509 -in certificate.der -inform der -text -noout
3、P7B/PKCS#7
PKCS7 – 加密消息語法(PKCS7),是各種消息存放的格式標准。這些消息包括:數據、簽名數據、數字信封、簽名數字信封、摘要數據和加密數據。
包含 --BEGIN PKCS--
和 --END PKCS7--
聲明。可以包含證書和證書鏈,但是不包含私鑰。
- Base64 編碼的 ASCII 文件
- 擴展名為
.p7b, .p7c
- 多平台支持。如:Windows OS、Java Tomcat
4、PFX/PKCS#12
Predecessor of PKCS#12。PKCS12(個人數字證書標准)用於存放用戶證書、crl、用戶私鑰以及證書鏈。PKCS12 中的私鑰是加密存放的。
對 Unix 服務器來說,一般 .crt
和 .key
是分開存放在不同文件中的。但 Windows 的 IIS 則將它們存在一個 .pfx
文件中。因此這個文件包含了證書及私鑰,這樣會不會不安全?應該不會, .pfx
通常會有一個“提取密碼”,你想把里面的東西讀取出來的話,它就要求你提供提取密碼。.pfx
使用的是 DER 編碼。
生成 .pfx
的方法:
$ openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt
其中 CACert.crt 是 CA 的根證書,有的話也通過 -certfile
參數一起帶進去。
PFX/PKCS#12 作用:主要用於存儲服務器證書,任何中間證書和私鑰存於一個可加密文件中。
PFX/PKCS#12 特點:
- 二進制文件
- 擴展名為
.pfx, .p12
- 典型用於 Windows OS 導入導出證書和私鑰
5、CSR
Certificate Signing Request,即證書簽名請求。這個並不是證書,而是向 CA 獲得簽名證書的申請。其核心內容是一個公鑰(當然還附帶了一些別的信息),在生成這個申請的時候,同時也會生成一個私鑰,私鑰要自己保管好。做過 iOS App 的朋友都應該知道是怎么向蘋果申請開發者證書。.csr
查看方法:
# 如果是 DER 格式的話照舊加上 -inform der $ openssl req -noout -text -in my.csr
生成 X509 數字證書前,一般先由用戶提交證書申請文件,然后由 CA 來簽發證書。大致過程如下:
-
用戶生成自己的公私鑰對
構造自己的證書申請文件,符合 PKCS#10 標准。該文件主要包括了用戶信息、公鑰以及一些可選的屬性信息,並用自己的私鑰給該內容簽名; -
用戶將證書申請文件提交給 CA
CA 驗證簽名,提取用戶信息,並加上其他信息(比如:頒發者等信息),用 CA 的私鑰簽發數字證書;
說明:數字證書(如x.509)是將用戶(或其他實體)身份與公鑰綁定的信息載體。一個合法的數字證書不僅要符合 X509 格式規范,還必須有 CA 的簽名。用戶不僅有自己的數字證書,還必須有對應的私鑰。X509 v3 數字證書主要包含的內容有:證書版本、證書序列號、簽名算法、頒發者信息、有效時間、持有者信息、公鑰信息、頒發者 ID、持有者 ID 和擴展項。
操作舉例
向 CA 申請證書:
$ openssl req -newkey rsa:2048 -new -nodes -keyout my.key -out my.csr
把 .csr
交給 CA,CA 對此進行簽名,完成。保留好 .csr
,當權威證書頒發機構頒發的證書過期的時候,還可以用同樣的 .csr
來申請新的證書,key 保持不變。
或者生成自簽名的證書:
$ openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
在生成證書的過程中會要你填一堆的東西,其實真正要填的只有 Common Name。通常填寫你服務器的域名,如:yourcompany.com
,或者你服務器的 IP 地址,其它都可以留空。
三、其他擴展名的證書文件
.crt
應該是 Certification 的縮寫。常見於 Unix 系統,編碼有可能是 PEM,也可能是 DER,大多數應該是 PEM 編碼。
.cer
應該是 Certification 的縮寫。常見於 Windows 系統,編碼有可能是 PEM,也可能是 DER,大多數應該是 DER 編碼。
.key
通常用來存放一個公鑰或者私鑰,並非 X.509 證書,編碼同樣可能是 PEM 或 DER。
四、證書不同格式間的轉換
1、PEM
PEM 轉為 DER
$ openssl x509 -outform der -in certificate.pem -out certificate.der
PEM 轉為 P7B
$ openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CAcert.cer
PEM 轉為 PFX
$ openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CAcert.crt
2、DER
DER 轉為 PEM
$ openssl x509 -inform der -in certificate.cer -out certificate.pem
3、P7B
P7B 轉換為 PEM
$ openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
P7B 轉換為 PFX
# 先將 P7B 轉為 PEM $ openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer # 再將 PEM 轉為 PFX/P12 $ openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CAcert.cer
4、PFX
x509
到 pfx
:
$ openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx
PKCS#12
與 PEM
的相互轉換:
# 從 cert.p12 中提取 私鑰,不包含證書,私鑰不加密,輸出為 PEM 格式 $ openssl pkcs12 -nocerts -nodes -in cert.p12 -out privatekey.pem # 從 cert.p12 中,只輸出 client 證書,不輸出私鑰,輸出為 PEM 格式 $ openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem # 將密鑰與證書合成為 cert.p12 $ openssl pkcs12 -export -in cert.pem -out cert.p12 -inkey key.pem
從 PFX
格式文件中提取私鑰
格式文件(.key
):
$ openssl pkcs12 -in mycert.pfx -nocerts -nodes -out mycert.key
PFX 轉換為 PEM
$ openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
注意:將 PFX 轉換為 PEM 格式時,OpenSSL 會將所有的證書和私鑰保存到一個文件中。需要使用文本編輯器打開,將每個證書和私鑰(包括 BEGIN/END
聲明)保存到自己獨立的文本文件中,並且分別保存為 certificate.cer, CAcert.cer, privateKey.key
。
5、BKS
在一些 Java 環境(如 Android)中,需要 BKS 格式證書。一般做法是將 P12 轉為 BKS:
# 先使用 openssl 把 crt 和 key 轉換為 p12 證書 $ openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 # 使用 keytool 把 p12 轉換為 bks 證書 $ keytool -importkeystore -srckeystore client.p12 -srcstoretype pkcs12 -destkeystore client.bks -deststoretype bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-ext-jdk15on-158.jar
使用 KeyTool 轉換為 BKS 格式時,需要 bcprov-ext-jdk15on-158.jar
,可以在這里找到。文件路徑直接帶在 -providerpath
參數后面即可。也可以放到如下路徑:jdk/jre/lib/ext
。
五、一些其他格式的介紹
JKS
Java Key Storage,這是 Java 的專利,跟 OpenSSL 關系不大。利用 Java 的一個叫 keytool 的工具,可以將 .pfx
轉為 .jks
,keytool 也能直接生成 .jks
。JKS 文件格式被廣泛的應用在基於 Java 的 Web 服務器、應用服務器、中間件。可以將 JKS 文件導入到Tomcat、 WebLogic 等軟件。
KDB
通常可以將 Apache/OpenSSL 使用的“KEY文件 + CRT文件”格式轉換為標准的 IBM KDB文件。KDB 文件格式被廣泛的應用在 IBM 的 WEB 服務器、應用服務器、中間件。你可以將 KDB 文件導入到 IBM HTTP Server、IBM Websphere 等軟件。
OCSP
在線證書狀態協議(Online Certificate StatusProtocol, rfc2560),於實時表明證書狀態。OCSP 客戶端通過查詢 OCSP 服務來確定一個證書的狀態,可以提供給使用者一個或多個數字證書的有效性資料,它建立一個可實時響應的機制,讓用戶可以實時確認每一張證書的有效性,解決由CRL引發的安全問題。OCSP 可以通過 HTTP 協議來實現。rfc2560 定義了 OCSP 客戶端和服務端的消息格式。
CRL
證書吊銷列表(Certification Revocation List)是一種包含撤銷的證書列表的簽名數據結構。CRL 是證書撤銷狀態的公布形式,CRL 就像信用卡的黑名單,用於公布某些數字證書不再有效。CRL是一種離線的證書狀態信息。它以一定的周期進行更新。CRL 可以分為完全 CRL和增量 CRL。在完全 CRL中包含了所有的被撤銷證書信息,增量 CRL 由一系列的 CRL 來表明被撤銷的證書信息,它每次發布的 CRL 是對前面發布 CRL的增量擴充。基本的 CRL 信息有:被撤銷證書序列號、撤銷時間、撤銷原因、簽名者以及 CRL 簽名等信息。基於 CRL 的驗證是一種不嚴格的證書認證。CRL 能證明在 CRL 中被撤銷的證書是無效的。但是,它不能給出不在 CRL中的證書的狀態。如果執行嚴格的認證,需要采用在線方式進行認證,即 OCSP認證。一般是由CA簽名的一組電子文檔,包括了被廢除證書的唯一標識(證書序列號),CRL用來列出已經過期或廢除的數字證書。它每隔一段時間就會更新,因此必須定期下載該清單,才會取得最新信息。
SCEP
簡單證書注冊協議。基於文件的證書登記方式需要從您的本地計算機將文本文件復制和粘貼到證書發布中心,和從證書發布中心復制和粘貼到您的本地計算機。 SCEP可以自動處理這個過程但是CRLs仍然需要手工的在本地計算機和CA發布中心之間進行復制和粘貼。
六、參考資料
- 原文:What are the differences between PEM, DER, P7B/PKCS#7, PFX/PKCS#12 certificates
- 參考 《那些證書相關的玩意兒(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)》 部分內容做了補充
- 常見數字證書及協議介紹
- RSA私鑰和公鑰文件格式 (pkcs#7, pkcs#8, pkcs#12, pem)
- ASN.1 key structures in DER and PEM
- openSSL將.crt證書生成.bks
(完)