使用 Java 中的 Keytool 將 p7b 檔案匯入 Java 金鑰庫
1. 引言
在開發 Java 生產應用程式時,我們經常需要設定 HTTPS、啟用安全出站通訊或管理信任庫。 Keytool是處理所需金鑰和憑證並管理 Java 金鑰庫的標準工具。
在本教程中,我們將專注於一個具體任務:使用 keytool 將p7b憑證檔案匯入 Java 金鑰庫。
2. 理解 P7B (PKCS#7) 格式
在深入了解匯入 P7B 檔案的步驟之前,有必要回顧並了解PKCS#7 格式。
在密碼學中,PKCS#7 是儲存加密簽章或加密資料的標準語法。
這種格式的常見用途是儲存 SSL 憑證。通常,憑證包以.p7b檔案格式儲存和共用。
2.1. 證書包
建立用於開發的自簽名憑證時,通常只需要一個私鑰和一個包含公鑰的自簽名憑證。但是,對於需要在網路上公開存取的生產應用程序,我們通常需要讓已知的憑證授權單位 (CA) 驗證我們的憑證。
瀏覽器透過驗證網站的憑證來驗證其合法性。每個網站都會提交自己的證書,以及指向一系列中間證書的信息,最終指向證書頒發機構 (CA) 的根證書。由於瀏覽器信任 CA,因此任何提供已驗證憑證且憑證鏈清晰(指向根 CA 憑證)的網站都被認為是有效的。
憑證經憑證授權單位 (CA) 驗證後,通常會提供一個憑證鏈,該憑證鏈包含其自身的根憑證以及零個或多個中間憑證。此憑證鏈以憑證包的形式提供,有時以.p7b檔案的形式提供。
2.2. P7B格式
P7B 檔案是一種 PKCS#7 容器,可以儲存一個或多個憑證。它可以採用二進位 DER 格式或 Base64 PEM 格式進行編碼。
在使用 Java 伺服器(例如 Tomcat)時,我們需要確保將捆綁包中的所有憑證匯入到我們的金鑰庫中,以證明我們憑證的有效性。
所有現代裝置上的瀏覽器都能識別由憑證授權單位 (CA) 驗證的憑證。在憑證驗證過程中,CA 通常會分享我們網站的簽署公鑰憑證以及憑證鏈,也稱為憑證包。
有時,證書包以.p7b檔案的形式提供。需要注意的是,根據編碼方式的不同,其內容可能無法在純文字編輯器中直接讀取。因此,我們需要一些工具來處理這些憑證並將其匯入到金鑰庫中。
3. 準備 P7B 文件
既然我們已經了解了 P7B 格式,讓我們深入了解這個過程。
在匯入憑證包之前,我們需要一個包含該憑證包的檔案。由於我們沒有憑證授權單位 (CA) 提供的.p7b文件,我們將使用 Baeldung.com 提供的公鑰憑證。
首先,我們將下載該鏈並將其轉換為 P7B 檔案格式。
3.1 下載憑證包
大多數現代瀏覽器都允許將憑證匯出為 PKCS#7 格式編碼的檔案。不過,我們將使用 Linux 終端機上的openssl命令,透過完整的命令列介面來實現:
$ openssl s_client -connect www.baeldung.com:443 -showcerts </dev/null
此命令會列印出多個證書以及每個證書的一些相關資訊。每個證書都可以透過其起始和結束標記輕鬆識別:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
現在我們可以複製每個憑證(包括標記),並將它們儲存為單獨的.pem檔案。所以現在我們有三個檔案site.pem, intermediate.pem and root.pem 。
現在讓我們用它們來建立一個.p7b檔案包:
$ openssl crl2pkcs7 -nocrl -certfile site.pem -certfile intermediate.pem \
-certfile root.pem -out site-chain.p7b
最後,我們可以驗證所有權益憑證是否都包含在憑證包中:
$ openssl pkcs7 -print_certs -in site-chain.p7b -noout
我們看到三份證書印得清晰無誤,符合預期。
3.2. 導入 P7B 檔案的問題
現在我們有了有效的.p7b檔案格式的憑證包,讓我們用keytool來檢查一下:
$ keytool -printcert -file site-chain.p7b
此命令會清楚地列印有關這三個證書的資訊。
讓我們嘗試直接導入:
$ keytool -importcert -file site-chain.p7b -keystore test-keystore.jks -alias site
輸出結果顯示錯誤:
keytool error: java.lang.Exception: Input not an X.509 certificate
憑證匯入失敗,因為keytool -importcert期望輸入檔案恰好包含一個 X.509 PEM 或 DER 編碼的憑證。
4. 導入 P7B 文件
我們發現,使用 keytool 直接匯入憑證包可能會出現問題。解決方法是將證書包拆分成單一證書,然後逐一匯入這些證書。
4.1. 轉換為 PEM 編碼
要將捆綁包拆分成單一 PEM 文件,首先,我們將捆綁包從 PKCS #7 格式轉換為 PEM 編碼格式:
$ openssl pkcs7 -print_certs -in site-chain.p7b -out site-chain.pem
這將產生一個包含一個或多個 X.509 憑證的 PEM 檔案:
-----BEGIN CERTIFICATE-----
.......
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
.......
-----END CERTIFICATE-----
現在我們可以使用keytool匯入憑證了。
4.2. 導入 PEM 包
現在文件格式與keytool導入選項相容,我們可以執行輸入操作:
$ keytool -importcert -file site-chain.pem -keystore test-keystore.jks -alias site
此命令要求我們設定密鑰庫密碼,並詢問我們是否信任該證書。然後輸出顯示成功:
Trust this certificate? [no]: yes
Certificate was added to keystore
這會將網站的憑證匯入到別名site下。
如果我們需要在同一個金鑰庫中同時包含中間證書和根證書,那麼我們需要分別匯入它們。我們可以從site-chain.pem檔案複製每個憑證(包括起始和結束標記),並將它們儲存為單獨的.pem檔案。這樣我們就有了兩個檔案: intermediate.pem和root.pem 。
我們也可以使用相同的命令,但使用不同的輸入檔案和別名來匯入根憑證和中間憑證:
$ keytool -importcert -file root.pem -keystore test-keystore.jks -alias root
$ keytool -importcert -file intermediate.pem -keystore test-keystore.jks -alias intermediate
4.3. 驗證導入
現在所有憑證都已匯入,讓我們來驗證一下:
$ keytool -list -v -keystore test-keystore.jks
此命令會要求輸入先前設定的密碼,然後顯示所有已匯入證書的詳細資訊。在輸出結果的開頭,我們看到:
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 3 entries
好了,我們的金鑰庫現在可以使用了。
5. 結論
本文探討了 keytool 如何處理 PKCS#7 ( .p7b ) 格式的憑證包。雖然這些文件可以包含完整的憑證鏈,但並非總是可以直接匯入。
我們了解到keytool需要 DER 或 PEM 格式的 X.509 證書,而不是 PKCS#7 等容器格式。將.p7b包轉換為單一憑證可以確保匯入過程成功且可預測。