數位憑證相關的知識真的頗為複雜,以前對這方面的理解都過於片段,上網找到的文章資料就算真的將命令打對了,要嘛沒有講解為什麼,要嘛就是在觀念講解的部分不夠清楚,或是內文描述有許多謬誤之處,以至於每次遇到憑證問題都深感信心不足。我最近又多花了些時間研究,這次對整個數位憑證架構總算有點理解,今天這篇文章主要想來介紹關於憑證格式方面的觀念。
在了解憑證格式之前,建議各位先行 瞭解公開金鑰加密 (Public Key Cryptography) 與 瞭解數位憑證 (Digital Certificates) 的基本觀念,這部分的知識與觀念是幫助你理解 公開金鑰基礎建設 (Public Key Infrastructure) (PKI) 的基石。
簡單來說,PKI 基礎建設包含了:
- A certificate authority (CA) that stores, issues and signs the digital certificates
一個 憑證授權單位 (CA),用來儲存、發行、簽署數位憑證。
- A registration authority which verifies the identity of entities requesting their digital certificates to be stored at the CA
一個 註冊機構 (RA),用來驗證申請憑證的實體身分 (個人、法人、應用程式、...)。
- A central directory—i.e., a secure location in which to store and index keys
一個 中央目錄,用來儲存金鑰與檢索金鑰的地方。
- A certificate management system managing things like the access to stored certificates or the delivery of the certificates to be issued.
一套 憑證管理系統,用來管理像是存取憑證、傳遞已簽發憑證的系統。
- A certificate policy stating the PKI's requirements concerning its procedures. Its purpose is to allow outsiders to analyze the PKI's trustworthiness.
一套 憑證管理政策,用來規範維護 PKI 基礎架構下所有的管理程序,確保憑證與金鑰的安全性。
在開發與測試的情境下,你只要自己建立一個 憑證授權單位 (CA) 外加一套 憑證管理系統 (e.g. OpenSSL ),就可以自行架設一整套 PKI 基礎建設。
基本上,要建立一個 憑證授權單位 (CA),首先你必須要先建立一個 私密金鑰 (Private key),用來對未來要簽發的 憑證 (Certificate) 進行 簽章 (Signature)。這部分你可以使用的管理工具很多,在 Windows 平台,你可能會用 MakeCert 或 PowerShell 來建立 CA 所需的私密金鑰與憑證;而在 Linux 平台,大部分人都會選擇採用複雜的 OpenSSL 工具,這套工具參數與選項全部加起來應該有數百種組合,功能強大。
1. 使用 MakeCert 工具建立 CA 的命令如下
這個 MakeCert 工具會隨著 Visual Studio 或 Windows SDK 安裝的過程自動安裝,主要可以產生僅供測試用途的 X.509 憑證 (RFC5280)。
makecert -n "CN=Will Certificate Authority" -cy authority -a sha1 -sv "CA-PrivateKey.pvk" -r "CA-Certificate.cer"
2. 使用 OpenSSL 工具建立 CA 的命令如下
這個 OpenSSL 則是跨平台的 TLS/SSL 工具組,可以用來建立、簽發、轉換憑證格式等多功能用途。
openssl genrsa -des3 -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt
從上述兩個工具所產生的私密金鑰與憑證你就會發現,他們之間的檔案內容格式完全不一樣,MakeCert 所建立的私密金鑰與憑證是二進位格式;而 OpenSSL 所建立的私密金鑰與憑證預設為文字格式。但事實上,不管你用什麼工具產生私密金鑰與憑證,都在做一樣的事情,只是格式不同而已,而且不同格式之間也可以互相轉換。
接著,我們就要進入重點了,介紹這些私密金鑰與憑證檔案的格式種類。
一般來說,跨平台共通標準的編碼格式有兩種:
- DER (Distinguished Encoding Rules)
- 檔案內容為二進位格式
- DER 是 ASN.1 語法標準下的其中一種二進位的編碼方法
- 常見副檔名有
- *.der
- *.cer (常用於Windows作業系統)
- *.crt (這種副檔名比較不好猜格式,建議少用)
- PEM (Privacy Enhanced Mail)
- 檔案內容為文字格式
- 其內容是 DER 檔案內容經由 Base64 編碼過後的字串
- 以 -----BEGIN ***----- 開頭,以 -----END ***----- 結尾
- 詳見 RFC 1421、RFC 1422、RFC 1423、RFC 1424
- 常見副檔名有
- *.pem
- *.cert (常用於Linux作業系統)
- *.crt (這種副檔名比較不好猜格式,建議少用)
備註:CRT 與 CER 或 CERT 都是 Certficiate (憑證) 這個單字的縮寫。
所以無論你想要建立的是私密金鑰或是憑證,都可以自由選擇想要儲存的格式。但是在這三十多年的數位憑證發展過程中,出現了許許多多不同的規格,用著各種不同的格式來保存私密金鑰或憑證,以至於 OpenSSL 變得這麼複雜,參數與選項都多到爆炸,任何一個初學者想好好掌握工具使用,大多會被排山倒海的專有名詞給嚇跑。
以下我就來介紹幾個不同的檔案格式:
- KEY
- 用來存放一個公鑰或者私鑰,這種檔案並沒有事先定義格式,只是意義上的「私密金鑰」而已。
- 編碼格式可能是 PEM 或 DER,但通常是 PEM 格式 (因為在 Linux 或 Node.js 環境下很常用)
- 金鑰內容可能是加密過的,但也可能是未加密過的,要依據實際內容而定。
- 常見副檔名有
- PVK (Microsoft PrivateKey Blob)
- 微軟專屬的「私密金鑰」格式
- PVK 是二進位檔案,檔案內容格式可參見:PVK file format
- 透過 MakeCert 所產生的私密金鑰,預設就是 PVK 格式
- 這種檔案只有「私密金鑰」,不會包含「憑證」在內
- PVK 可以透過 OpenSSL 工具轉換為 PEM 格式,命令如下:
- openssl rsa -in "ca.pvk" -inform PVK -out ca.key -outform PEM
- PVK 也可以轉換為 PFX 格式,透過 WDK 內建的 Pvk2Pfx 工具,就可以進行轉換:
- "C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x64\pvk2pfx.exe" -pvk "server.pvk" -spc "server.cer" -pfx "server.pfx"
- 備註:通常 WDK (Windows Driver Kit) 會隨著 Visual Studio 安裝過程自動安裝好。
- 常見副檔名有
- CSR (Certificate Signing Request) / PKCS #10
- CSR = 憑證簽署請求檔
- 當你需要讓 CA 幫你簽署一份憑證時,通常要先準備一把 私密金鑰 (Private Key),然後先產生 CSR 檔案,這份 CSR 檔案將包含 主體資訊 (Subject) 與一把 公開金鑰 (Public Key),然後將 CSR 檔案提交給 CA 進行簽署,之後就可以由 CA 簽署過,並產生一份含有 公開金鑰 (Public Key) 的 憑證 (Certificate) 回來。
- 主體資訊 (Subject) 通常包括憑證的摘要資訊,例如國家代號、省分、城市、組織名稱、單位名稱、一般名稱 (Common Name) 等等,也可以外加一些 擴充屬性 ('extra' attributes) 供 CA 簽署時參考。
- 詳見 RFC 2986 - PKCS #10: Certification Request Syntax Specification
- 你可以透過 OpenSSL 工具建立一個 CSR 檔案,命令如下:(先擁有私密金鑰,再建立 CSR 檔案)
- openssl genrsa -out server.key 2048
- openssl req -new -sha256 -out server.csr -key server.key
- 你可以透過 OpenSSL 工具查看 CSR 檔案的請求內容,命令如下:
- openssl req -noout -text -in server.csr
- 常見副檔名有
- P7B / PKCS#7
- 常見副檔名有
- *.p7b
- *.p7c
- *.keystore (在 Java 開發環境下常用這個副檔名)
- PKCS#8
- PFX / PKCS#12 (predecessor of PKCS#12)
- 在 Linux 平台下,通常憑證檔與金鑰檔都是分開保存的,所以當在設定網站 TLS/SSL 時,通常會需要設定兩個檔案。
- 在 Windows 平台下,IIS 改用 PFX 檔案格式,將憑證與金鑰結合在一個檔案裡,並加入一些擴充屬性(Metadata)。
- 後來 PKCS 推出一份 PKCS#12 規格 (二進位格式),可以在一個檔案中同時包含憑證、中繼憑證、私密金鑰,取代 PFX 成為標準格式。
- 詳見 RFC 7292 - PKCS #12: Personal Information Exchange Syntax v1.1
- 產生 *.pfx 檔案通常需要一組密碼,保護 PFX 檔案的安全性。
- 你隨時可以將 *.pfx 檔案轉換成 PEM 編碼格式 (檔案中將會包含所有憑證與金鑰的 PEM 格式內容),OpenSSL 的指令如下:
- openssl pkcs12 -in mysite.pfx -out mysite.pem -nodes
- 備註:上述命令的 -nodes 參數,其實是 No DES 加密的意思,也就是產生出來的私密金鑰不需要加密。
- 產生 PFX 檔案的 OpenSSL 命令如下:
- openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx
- openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx -certfile CACert.crt
- 備註:上述命令的 -certfile 用來將額外的憑證一併加入 PFX 檔案,通常是一個以上的中繼憑證或根憑證。
- 常見副檔名有
- JKS (Java Key Storage)
終於介紹完了到目前為止我所知道的金鑰與憑證格式,當然在 Wikipedia 的 PKCS (Public Key Cryptography Standards) 文件中,你還會看到更多其他不同時期定義出來的規格,有需要再去查看了解即可。
相關連結