原文地址:http://blog.52sox.com/use-ope...html
近期在項目中iOS須要用到APNs的推送,而公司的iOS女同事(純哥)只給了我2個p12格式的文件。忽然發現,證書的轉換問題仍是比較常見的,好比以前支付開發。而在程序中,實際須要使用的是pem格式的證書,所以這裏涉及到證書之間的轉換問題。
因爲私鑰和證書能夠以不一樣格式的存儲,這意味着咱們須要對它們進行轉換。而大多數經常使用的格式以下,首先是證書的格式:node
二進制的DER證書,包含X.509證書爲原始格式,使用DER ASN.1編碼。算法
ASCII的PEM證書,包含1個base64編碼的DER證書,以-----BEGIN CERTIFICATE-----
開頭而以-----END CERTIFICATE-----
結束。服務器
PKCS#7證書,1個複雜格式的設計用於傳輸簽名或加密數據,定義在RFC 2315中。一般以.p7b
和.p7c
做爲後綴且能夠包含整個證書鏈。這種格式被Java的keytool工具支持。編輯器
PKCS#12(PFX)的證書和私鑰,1個複雜的格式它能夠存儲和保護1個服務器的私鑰並和1個完整的證書鏈一塊兒。它一般以.p12
和.pfx
爲後綴。這種格式經常使用於微軟的產品,不過也能夠用於客戶端證書。工具
而後是對應的私鑰的格式:編碼
二進制的DER私鑰,包含1個私鑰以原始形式,使用DER ASN.1編碼。OpenSSL以它傳統的SSLeay格式建立私鑰,不過也可使用另外1種稱爲PKCS#8,但不普遍使用的格式(定義在RFC 5208)。在OpenSSL中可使用pkcs8
命令來進行PKCS#8格式的處理操做。加密
ASCII格式的私鑰,包含1個base64編碼的DER私鑰,有些時候有一些額外的元信息,例如密碼保護採用的算法。設計
說了這麼多,能夠發現對於私鑰之間的轉換就簡單的不少,只能在DER和PEM格式之間進行轉換。而相比證書之間的轉換,就稍微複雜一些。
若是有興趣還能夠查看個人另外一篇文章PKI格式標準查看其概念。
在這裏,咱們須要將PKCS#12格式的文件中提取出私鑰和證書。下面咱們先從PEM和DER格式的轉換開始:code
PEM和DER格式證書的轉換能夠經過OpenSSL提供的x509工具來完成。下面咱們轉換1個DER格式的證書爲PEM:
sky@sky-pc:~$ openssl x509 -inform DER -in private_key.der -outform PEM -out private_key.pem
在這裏,咱們經過-inform
參數指定輸入的格式爲DER,經過-in
參數指定輸入的文件名稱,然後對應的-outform
和-out
用於指定輸出的格式及文件名稱。
一樣的,咱們也能夠將PEM格式的整數轉換爲DER格式:
sky@sky-pc:~$ openssl x509 -inform PEM -in private_key.pem -outform DER -out private_key.der
下面咱們來看下如何從PKCS#12格式中提取出私鑰和證書。
咱們可使用OpenSSL提供的pkcs12
命令來實現PKCS#12格式的操做,首先咱們將證書和私鑰導出爲PEM格式:
sky@sky-pc:~$ openssl pkcs12 -in key.p12 -out key.pem -nodes Enter Import Password: MAC verified OK
在這裏,咱們經過-in
參數指定傳入的文件名稱,而-out
文件指定輸出的文件名稱,而-nodes
參數表示不對私鑰進行加密。在這個過程當中,咱們須要輸入簽名時的密碼。
若是咱們不添加-nodes
參數,將是以下的結果:
sky@sky-pc:~$ openssl pkcs12 -in key.p12 -out key.pem Enter Import Password: MAC verified OK Enter PEM pass phrase: Verifying - Enter PEM pass phrase:
能夠看到,驗證簽名成功後還須要咱們從新輸入新的加密口令。而在導出的文件中能夠看到此時文件的內容爲:
... -----BEGIN ENCRYPTED PRIVATE KEY----- MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIPdUUocbjDXUCAggA ... -----END ENCRYPTED PRIVATE KEY-----
而添加-nodes
後的結果爲:
... -----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC+QDKKakQ0fcvH ... -----END PRIVATE KEY-----
以後,咱們就可使用編輯器打開輸出的key.pem文件,手動的拆分它們爲獨立的私鑰、證書和中間證書文件。
做爲程序猿,通常人都是懶惰的,這個繁瑣的操做能不能簡便些呢,讓機器本身去完成呢?
實際上是能夠作到的,在OpenSSL中提供這樣的操做,咱們先來看看不導出證書的操做,這樣咱們就能夠獲得私鑰了:
sky@sky-pc:~$ openssl pkcs12 -in key.p12 -nocerts -out private_key.pem -nodes Enter Import Password: MAC verified OK
能夠看到,在這裏咱們多添加了1個-nocerts
的參數就作到了不導出證書的操做。那麼不導出私鑰的操做應該以下:
sky@sky-pc:~$ openssl pkcs12 -in key.p12 -nokeys -out cert.pem -nodes Enter Import Password: MAC verified OK
接下來,咱們該如何將PEM格式的證書和私鑰導出爲PKCS#12格式呢,咱們能夠這樣來操做:
sky@sky-pc:~$ openssl pkcs12 -name "My Certificate" -export -out fd.p12 -inkey key.pem -in cert.pem -certfile fd-chain.crt Enter Export Password: Verifying - Enter Export Password:
其中,-name
選項指定了證書中的friendlyName,而-certfile
指定信任鏈的文件名稱。
最後,咱們還能夠經過-clcerts
和-cacerts
選項指定是否只導出客戶端及CA證書。
爲了轉換PEM爲PKCS#7,咱們可使用crl2pkcs7
命令。
sky@sky-pc:~$ openssl crl2pkcs7 -nocrl -out key.p7b -certfile cert.pem -certfile fd-chain.crt
那麼,生成的文件頭部將以-----BEGIN PKCS7-----
開始。
最後,爲了轉換PKCS#7爲PEM,咱們可使用pkcs7
命令:
sky@sky-pc:~$ openssl pkcs7 -in key.p7b -print_certs -out key1.pem
在這裏,咱們使用-print_certs
參數將輸入的證書輸出。
若是咱們想將PKCS#8格式的私鑰轉換爲SSLeay格式,咱們能夠這樣來操做:
sky@sky-pc:~$ openssl rsa -in key.pem -out ssleay.pem writing RSA key
而此時文件的內容將以下所示:
-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAvkAyimpENH3Lx4d8VH96XCYfKfCZ7qVtNuVseAvkSTC0q5dw ... -----END RSA PRIVATE KEY-----
能夠看到頭部和尾部多追加了RSA的字樣。
而若是要將傳統的SSLeay私鑰轉換爲PKCS#格式,咱們須要使用pkcs8
命令:
sky@sky-pc:~$ openssl pkcs8 -topk8 -in ssleay.pem -out pkcs8_key.pem Enter Encryption Password: Verifying - Enter Encryption Password:
默認狀況下,會爲該格式進行1個加密的處理,可是咱們能夠經過-nocrypt
參數讓其不進行加密處理:
sky@sky-pc:~$ openssl pkcs8 -topk8 -nocrypt -in ssleay.pem -out pkcs8_key.pem
能夠咱們便實現了將傳統的SSLeay格式轉換爲PKCS#8格式了。
下面咱們來生成APNs推送時須要的證書。
sky@sky-pc:~$ openssl pkcs12 -in cer.p12 -clcerts -nokeys -out cert.pem -nodes Enter Import Password: MAC verified OK sky@sky-pc:~$ openssl pkcs12 -in cer.p12 -nocerts -out key.pem -nodes Enter Import Password: MAC verified OK sky@sky-pc:~$ cat cert.pem key.pem > certs.pem
咱們先只導出客戶端的證書,而後是私鑰,最後咱們將2個文件的內容合併在1個文件中便可。
參考文章:
https://www.feistyduck.com/li...
http://juliusdavies.ca/common...
https://superuser.com/questio...