- OpenSSL中雖然使用PEM作為基本的文件編碼格式,但是,由于不同的對象其封裝的標準格式不太一樣,所以經常會導致讀者產生迷惑。此外,OpenSSL也支持DER編碼和過時的Netscape編碼格式(NET)
- OpenSSL的編碼是基于ASN.1標準的,ASN.1全稱為AbstractSyntaxNotationOne,是一種描述數字對象的方法和標準。ASN.1是一種結構化的數字對象描述語言,它包括了兩部分,分別為數據描述語言(ISO8824)和數據編碼規則(ISO8825)。
- ASN.1的數據描述語言標準允許用戶自定義基本數據類型,并可以通過簡單的數據類型組成更復雜的數據類型。比如一個復雜的數據對象,如X.509證書,就是在其他一些數據類型上定義的,而其他數據類型又是在更基本的數據類型上建立的,直到回溯到定義的最基本的數據類型。
- ASN.1提供了多種數據編碼方法,包括了BER,DER,PER和XER等。這些編碼方法規定了將數字對象轉換成應用程序能夠處理、保存和網絡傳輸的二進制編碼形式的一組規則。目前經常被采用的是BER(BasicEncodeRules)編碼,但是BER編碼具有編碼不唯一的性質,也就是說,一個相同的對象通過BER編碼可能會產生幾種不同的編碼數據。所以,在OpenSSL和其他密碼學相關軟件中經常使用BER的一個子集DER(DistinguishedEncodingRules)。對于每一個ASN.1對象,使用DER編碼得出的二進制編碼數據是唯一的。
- PEM編碼全稱是PrivacyEnhancedMail,是一種保密郵件的編碼標準。通常來說,對信息的編碼過程基本如下。
- 1 信息轉換為ASCI碼或其他編碼方式,比如采用DER編碼。
- 2 使用對稱加密算法加密經過編碼的信息。
- 3 使用BASE64對加密后的信息進行編碼。
- 4 使用一些頭定義對信息進行封裝,主要包含了進行正確解碼需要的信息,頭定義的格式形式如下:
- Proc_Type,4:ENCRYPTED??
- DEK-Info:cipher-name,ivec
- 其中,第一個頭信息標注了該文件是否進行了加密,該頭信息可能的值包括ENCRYPTED(信息已經加密和簽名),MIC-ONLY(信息經過數字簽名但沒有加密),MIC-CLEAR(信息經過數字簽名但是沒有加密,也沒有進行編碼,可使用非PEM格式閱讀),以及CLEAR;第二個頭信息標注了加密的算法及對稱加密塊算法使用的初始向量。
- 在這些信息的前面加上如下形式頭標注信息:—BEGIN PRIVACY-ENHANCED MESSAGE—
- 在這些信息的后面加上如下形式尾標注信息:—END PRIVACY-ENHANCED MESSAGE—
- OpenSSL的PEM編碼基本上是基于DER編碼之上的,也就是說,它在上述第一步采用的是DER編碼,所以,從本質上來說,OpenSSL的PEM編碼就是在DER編碼基礎上進行BASE64編碼,然后添加一些頭尾信息組成的。讀者可以做一個實驗,將OpenSSL簽發的PEM證書文件轉換成DER編碼(二進制),導入到WindowsIE中,然后再從WindowsIE以BASE64編碼的DER格式導出到另一個文件中,比較原始的PEM格式文件跟新導出的DER文件,讀者會發現其實是一樣的。事實上,OpenSSL也是將以這種方式導出的文件當成是PEM格式的文件進行解碼的。需要說明的是,OpenSSL的指令有對特定類型的文件(比如X.509證書文件)進行PEM和DER格式轉換的方法。由于OpenSSL里面的DER格式是指沒有經過BASE64編碼的DER格式,所以事實上就是在二進制的DER和BASE64編碼的DER(PEM)格式之間進行轉換。
- OpenSSL還支持一種老式的Netscape編碼格式(NET),由于這種格式現在基本上廢棄不用了,這里不再作更多的介紹。
證書編碼
X.509證書
- 數據編碼格式提供了封裝數據的基本方法,但是,對于具體的數據對象,比如證書,根據其包含的內容的不同,還有更具體的表達方式。
- 目前總的來說有三種常用的證書編碼格式:X.509證書、PKCS#12證書和PKCS#7證書。X.509證書是最經常使用的證書,它僅包含了公鑰信息而沒有私鑰信息,是可以公開進行發布的,所以X.509證書對象一般都不需要加密。
- 一個OpenSSL簽發的經過PEM編碼的X509證書看起來通常有如下的格式:

?
- 上述信息中,在“—BEGINCERTIFICATE—”和“—ENDCERTIFICATE—”之間就是PEM編碼的X.509證書。PEM編碼的數據信息總是包含在一對頭和尾組成的標識符之間,對于X.509證書來說,
- 除了上述形式的頭尾格式,還可能出現以下兩種不同的標識符:?

- 以上三種形式,OpenSSL都可以進行正確的處理和解碼。
- 讀者可能還會在OpenSSL實際簽發的證書文件中最前面發現很多可讀的證書明文解釋,事實上,這些只是增加了證書文件的可讀性,并不代表真正的數據。在其他軟件中,比如Windows軟件,可能并不支持這些額外的明文信息,所以,先要將“—BEGINCERTIFICATE—”之前的所有可讀信息去掉。刪除這些信息的方法很多,最簡單的是手動刪除。
- 此外,也可以使用x509指令,進行PEM到PEM的證書格式轉換,就可以去除明文可讀信息。
- 在Windows平臺,X.509證書文件的后綴名經常是der,cer或者crt,都是可以被自動識別的。當然,對于OpenSSL來說,后綴名是沒有實際意義的。
- OpenSSL的指令x509提供了對X.509證書進行格式轉換的方法,可以在DER,PEM和NET三種格式之間進行轉換。?
PKCS#12證書
- PKCS#12證書不同于X.509證書,它可以包含一個或多個證書,并且還可以包含證書對應的私鑰。OpenSSL對PKCS#12證書提供了支持,并且提供了專門用于處理PKCS#12證書的指令pkcs12。
- pkcs12指令可以將普通的X.509證書和私鑰封裝成PKCS#12證書,也可以將PKCS#12證書轉換成X.509證書,并提取出相應的私鑰。
- 一般來說,PKCS#12證書的私鑰是經過加密的,密鑰由用戶提供的口令產生。所以,無論在使用pkcs12指令編碼或者解碼PKCS#12證書的時候,一般都會要求用戶輸入密鑰口令。
- PKCS#12證書文件在Windows平臺和Mozila中支持的后綴名是p12或者pfx。如果要在IE或者Mozila中正確使用自己的證書,那么一般來說都要求轉換成包含公鑰和私鑰的PKCS#12證書導入到相關軟件中。
PKCS#7
- PKCS#7可以封裝一個或多個X.509證書或者PKCS#6證書(PKCS#6是一種證書格式,但是并不經常使用),并且可以包含CRL信息。PKCS#7證書也不包含私鑰信息,但是跟X.509證書不同的是,它可以包含多個證書,這就使得PKCS#7可以將驗證證書需要的整個證書鏈上的證書都包含進來,從而方便證書的發布和正確使用。
- OpenSSL提供了對PKCS#7格式文件的支持,并提供了crl2pkcs7和pkcs7兩個指令來生成和處理PKCS#7文件。可以使用他們在X.509證書和PKCS#7證書之間進行轉換和處理。
- PKCS#7文件在Windows平臺的合法后綴名是p7b。
密鑰編碼
- OpenSSL有多種形式的密鑰,很多情況下,需要把這些密鑰保存下來。OpenSSL提供了PEM和DER兩種編碼方式對這些要保存的密鑰進行編碼,而且都提供了相關指令可以使用戶在這兩種格式之間進行轉換。
- DER編碼存儲的密鑰文件是不可讀的,如果你樂意用文本編輯器打開它,那么將看到一些難以理解的符號,然而這很正常,因為這是一個二進制編碼的文件。
- PEM則不一樣,它要友好得多,因為PEM經過BASE64編碼。用文本編輯器打開PEM編碼的密鑰文件,可以看到跟證書類似,它們真正的編碼都包含在類似于:
- ——BEGIN XXXXX——
- ——END XXXXX——
- 這樣一對符號內,使用某些OpenSSL指令的一些選項后,你也許會在這對符號之前看到一些明文的信息,這些信息是編碼內容的明文解釋,并不是實際的數據,你要關注和使用的就是上述特殊符號內包含的內容。
- 密鑰總的來說有兩種,一種是可以公開的(比如公開密鑰對的公鑰),一種是不能公開的(比如公開密鑰對的私鑰)。那么,反映在編碼上,有的密鑰文件就會需要加密,有的就不需要加密。
- 一個經過加密的PEM編碼密鑰文件在上述的符號內會增加一些頭信息,這就是在前面介紹的PEM編碼的頭信息,這時候就派上用場了。這些頭信息主要是為密鑰解密的時候提供有用的信息,包括標記密鑰加密狀態、使用的加密算法及初始向量(對于塊加密算法來說)。
- 下面是一個經過加密的RSA私鑰的PEM編碼文件的例子:

?
- 可以看到,上述的PEM編碼的是RSA私鑰(RSAPRIVATEKEY),該密鑰經過了加密(ENCRYPTED),使用的加密算法是3DES的CBC方式(DES-EDE3-CBC),使用的IV向量是“86B0167E005535D2”。
- OpenSSL的指令提供了對密鑰加密的功能,并提供了多種可選的加密算法,這些算法都是對稱加密算法,比如DES和DES3等。OpenSSL的指令通常使用要求輸入口令的方式來生成用來加密密鑰數據的密鑰,這里的口令并非直接用來作為加密的密鑰,而是根據這個口令使用一系列HASH操作來生成一個用于加密密鑰數據的密鑰。在讀取這類加密的密鑰文件的時候,OpenSSL的指令同樣會要求你輸入用于解密的口令,當然,這個口令跟你加密密鑰時輸入的口令應該是一致的。
- OpenSSL對某些類型的密鑰也提供了一些標準的封裝格式,如PKCS#8和PKCS#12格式。PKCS#8是用于封裝需要保密的密鑰的規范格式,OpenSSL提供了pkcs8的指令來處理這類格式的文件。事實上,PKCS#12對密鑰的封裝就是采用了PKCS#8的格式。OpenSSL有各種各樣的密鑰類型需要采用上述方法進行編碼,比如RSA的公鑰和私鑰、DSA的公鑰和私鑰、DH密鑰參數,等等,它們的形式基本上是一樣的。
- 當然,無論采用什么加密方式對密鑰進行加密保存,以文件形式存儲的密鑰其安全性總是不可靠的,更值得信賴和推薦的方式是將密鑰存儲在不可導出的密鑰設備中,比如USBKey、SmartCard和加密機等硬件設備中,這些設備內部能夠完成加密操作,所以不需要將密鑰取出,這增加了密鑰的安全性。
?其他編碼
- 證書吊銷列表(CRL)是用戶驗證證書的重要參考資料,它主要包含了無效的證書列表,告訴用戶哪些證書是已經吊銷或無效的。當然,如果沒有CRL,或許你可以選擇另一種驗證方式,那就是使用在線證書服務協議(OCSP)。但不幸的是,OCSP并不總是能夠使用,比如你的網絡有時候可能不能接通OCSP服務器,那么你就要自行解決這個問題了。
- CRL是一種相對方便和獨立的解決方案,只要獲取了CA中心提供的在有效期內的CRL,基本上就能對證書的有效性進行驗證。OpenSSL提供CRL文件的生成、解釋及格式轉換等。
- PEM格式編碼的CRL一般包含在如下的一對符號內:
- ——BEGIN X.509 CRL——
- ——END X.509 CRL——
- 當然,還可以使用DER格式保存CRL。OpenSSL的指令提供了在PEM和DER之間對CRL進行格式轉換的功能。此外,你也可以把CRL和證書一起封裝成PKCS#7格式,使用的指令是crl2pkcs7。
- OpenSSL還包含了其他一些可以使用PEM編碼的有趣對象,當然,你可能永遠不需要使用這些對象。SSL協議的Session對象是其中之一,它可以被編碼成PEM格式,然后你可以使用OpenSSL的指令將它解釋成可以查看的明文。Session對象處理的指令是ses_id。
- OpenSSL還支持對Netscape證書序列格式(NSEQ)的PEM編碼和解釋,相應的指令是nseq。
?