14.4.4. CA 簽署(公開受信任)的憑證¶
當你掌控兩端時,自簽憑證即可運作。但如果是任意的用戶端(瀏覽器、手機、第三方軟體)必須連線到相機,而又無法要求它們去信任自訂憑證,那麼憑證就必須由那些用戶端已經信任的公開憑證授權單位(CA)來簽署。相機上的 TLS 程式碼與自簽情況完全相同——以 DER 形式的憑證與金鑰呼叫 load_cert_chain——只有你取得該憑證的方式不同。
最重要的一點:私鑰由你自己產生,而且它絕不離開你的機器。 CA 永遠看不到它。你送交給 CA 的是一份憑證簽署請求(CSR)——一個包含你的公鑰與網域名稱的小檔案——而你拿回來的是一張憑證(你的公鑰與名稱,由 CA 簽署)。金鑰與憑證是由兩個獨立步驟產生的兩個獨立檔案;CA 始終只處理公開的那一半。
整個流程都在一般的機器上完成(絕不在相機上):
取得網域名稱。 公開 CA 會為你所控制的 DNS 名稱(例如
cam.example.com)簽發憑證;它們不會為純 IP 位址或像mycam這樣僅限本地的名稱簽發。產生金鑰與 CSR。 一條 OpenSSL 指令即可產生私鑰與相符的 CSR。請使用你為自簽憑證所用的相同金鑰類型(參見 概念:信任、金鑰與檔案格式);建議使用 ECDSA P-256。
ECDSA P-256——建議:
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \ -nodes -keyout domain.key -out domain.csr \ -subj "/CN=cam.example.com" \ -addext "subjectAltName=DNS:cam.example.com"
ECDSA P-384——更強,但較大/較慢:
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 \ -nodes -keyout domain.key -out domain.csr \ -subj "/CN=cam.example.com" \ -addext "subjectAltName=DNS:cam.example.com"
RSA-2048——最大相容性:
openssl req -new -newkey rsa:2048 \ -nodes -keyout domain.key -out domain.csr \ -subj "/CN=cam.example.com" \ -addext "subjectAltName=DNS:cam.example.com"
請將
domain.key保密——這是你最終要放到相機上的金鑰檔案。domain.csr是你交給 CA 的檔案;它不含任何機密。提交 CSR 並證明你控制該網域。 兩種常見途徑在此處有所不同:
像 Let's Encrypt 這類自動化的 ACME CA,配合
certbot或acme.sh之類的工具,會替你完成步驟 2 與 3:它會產生金鑰、建立 CSR、自動回應挑戰(HTTP-01:在網域上透過連接埠 80 提供一個權杖;或 DNS-01:在其 DNS 中發布一筆 TXT 記錄),並寫出完成的檔案。商業 CA(直接購買或透過網域/主機代理商購買):你把
domain.csr的文字貼到網頁表單中,然後透過回覆驗證電子郵件、發布一筆 DNS 記錄,或在該網域的網頁伺服器上放置一個檔案來證明控制權。一旦通過驗證,你就能下載簽發的檔案。
收集簽發的檔案。 為了理解你所收到的東西,知道憑證會形成一條信任鏈會有幫助:你的網域憑證由一個中繼 CA 簽署,而後者又由一個根 CA 簽署。每一個環節都為其下方的環節背書。你最終會得到:
你的私鑰(來自步驟 2)。CA 從未擁有它;它留在你的機器上,並且是你最終要放到相機上的金鑰。
葉憑證——也稱為終端實體或伺服器憑證。這是針對你特定網域(
cam.example.com)的憑證:它包含你的公鑰與名稱,並由 CA 的中繼憑證簽署。這就是相機所出示用來表明自身身分的憑證。一張或多張中繼 CA 憑證(即「憑證鏈」或「CA bundle」)。CA 不會直接以其根憑證簽署你的葉憑證——根憑證的金鑰會離線保管並嚴加保護——所以它以中繼憑證簽署,而中繼憑證本身則由根憑證簽署。中繼憑證就是把你的葉憑證往上連接到根憑證的環節。
根憑證是信任錨點:一張屬於 CA、位於憑證鏈頂端的自簽憑證。你不會拿到它,也絕不會部署它,因為每個用戶端都已經擁有它——作業系統、瀏覽器、手機與程式語言執行環境都內建了一個根憑證的「信任儲存區」。用戶端透過走訪憑證鏈來信任你的葉憑證:它已經信任根憑證,根憑證為中繼憑證背書,而中繼憑證為你的葉憑證背書。(這正是你那單一的
server.der/cafile在自簽情況下所擔任的工作——在那裡你就是你自己的根。)fullchain 檔案不過是把葉憑證與中繼憑證串接成一個檔案,葉憑證在前,並刻意不含根憑證(傳送根憑證毫無意義——用戶端只會信任它已經擁有的根憑證)。一般的伺服器會出示整個 fullchain,讓任何用戶端都能走訪它。相機則做不到:它只載入並出示一張憑證——葉憑證——而無法同時傳送 CA 給你的中繼憑證。
你實際上會看到的檔案名稱:像
certbot這類 ACME 工具會寫出privkey.pem(你的金鑰)、cert.pem(僅葉憑證)、chain.pem(僅中繼憑證)與fullchain.pem(葉憑證 + 中繼憑證)。商業 CA 通常會給你一個用於葉憑證的.crt與一個用於中繼憑證的.ca-bundle,而.key則是你自己產生的那一個。轉換並複製。 將私鑰與葉憑證轉換為 DER,並完全依照 自簽憑證 上的方式複製到相機。相機接著會把它們作為其伺服器憑證出示,而標準用戶端會自動接受該連線,因為它們已經信任該 CA——不需要任何用戶端的設定。
小訣竅
在實務上,相機只出示葉憑證(而絕不出示中繼憑證)的結果會是這樣:
已經快取了該 CA 中繼憑證的用戶端——主流瀏覽器與 HTTPS 函式庫通常都有——會自行補完憑證鏈並順利連線。
依賴伺服器提供中繼憑證的用戶端,在對相機進行交握時會失敗。
如果每一個可能的用戶端都必須成功,就不要直接在相機上終結公開的 TLS。請在它前面放置一個閘道/反向代理,由它向外界提供完整的憑證鏈,並讓該代理透過上述的自簽流程連接相機。