14.4.6. 運維作業:金鑰、到期與疑難排解

每一台已部署裝置都會牽涉到三方面的憑證工作:在憑證上機後保護其私鑰、為憑證到期當天預作規劃,以及實務上會出現的少數錯誤情況。

14.4.6.1. 保護私鑰

每當相機出示憑證時(無論是作為 TLS 伺服器,還是作為 mTLS 中的用戶端),其私鑰都必須以純 DER 形式存放在裝置上,位於檔案系統或 ROMFS 中。以這種方式儲存時,相機上執行的任何程式碼都可讀取它,任何能實體接觸裝置的人也都能讀取:透過 USB 大量儲存裝置磁碟、REPL 提示字元,或是原始的快閃記憶體。ROMFS 與唯讀旗標只能防止修改,無法防止擷取請將任何隨裝置出貨的私鑰,視為決心堅定且具備實體或程式碼存取權限的攻擊者皆可取得。

這並不代表 TLS 毫無意義,它只是決定了你該如何部署:

  • 每台裝置使用獨一無二的金鑰與憑證。切勿在整個裝置群中燒錄同一把共用金鑰:一旦從單一裝置中擷取出該金鑰,攻擊者便能冒充每一台相機。每台裝置各自的金鑰能將入侵範圍侷限於該台裝置,而你可以在伺服器端將其撤銷或停用。

  • 讓憑證維持短期效期。遭竊的金鑰只有在其憑證仍有效時才有用;短效期加上例行輪替能限縮損害範圍(見下方 憑證到期與輪替)。

  • 能不在裝置上放置機密就盡量不放。如果你只需要驗證伺服器(伺服器驗證,而非 mTLS),那麼作為用戶端的相機只會儲存 CA 憑證(這是公開資訊),不會持有任何值得竊取的私鑰。

  • 切勿在公開的韌體映像中出貨金鑰。燒進你所散布之韌體建置版的 ROMFS 中的金鑰並非機密;任何下載該韌體的人都會擁有它。每台裝置的佈建意味著在通用韌體之後寫入金鑰,而不是寫在韌體之內

  • 限制波及範圍。將憑證所驗證的範圍縮到最小(最小權限原則),並確保單一外洩的裝置身分可以被撤銷或停用,而不影響其餘裝置。

如果你的威脅模型包含具備實體存取權限的攻擊者,請在設計時假設裝置金鑰終究會外洩,並讓系統在此情況下仍能存活,而不是假設能在毫無相關防護能力的硬體上將其保密。

14.4.6.2. 憑證到期與輪替

每張憑證都帶有一個有效期間。一旦過期,採用 ssl.CERT_REQUIRED 的對端就會拒絕連線,因此到期是一場真實且已排定的停機事件,而非理論上的風險。同時,相機的時鐘也必須正確,才能誠實地評估有效性檢查。

  • 自簽憑證。效期是你以 -days 選定的。當效期屆滿時,你必須重新產生金鑰/憑證並重新部署:重新複製 DER 檔案,或者若憑證是燒進去的,就重新建置並重新燒錄 ROMFS 映像。請挑選一個你確實記得要採取行動的 -days 值。

  • 公開 CA。這些憑證是刻意設計成短效期的。Let's Encrypt 簽發效期 90 天的憑證,並預期大約每 60 天就自動續期一次;沒有「安裝一次就不用再管」這種選項。

更宏觀的趨勢是單向的:受公開信任的 TLS 憑證最長有效期一直在縮短。它曾是 825 天,目前上限為 398 天,而 CA/Browser Forum 已採行一份時程表,將在 2029 年前逐步將其降至約 47 天。對裝置設計而言,啟示是:要假設憑證為短效期,且輪替必須自動化或至少例行化,切勿出貨一款依賴人工更換一張十年期憑證的產品。

在相機上的實務做法是:優先採用無須重新燒錄即可更換憑證的設計(可寫入的檔案系統搭配遠端更新途徑,或讓相機作為用戶端去信任一個你集中輪替的 CA)。如果憑證必須存放在 ROMFS 中,請依其效期排定韌體更新。

14.4.6.3. 疑難排解

  • 時鐘必須先設定。自開機以來尚未設定時鐘的相機,會無法通過憑證有效性檢查,請先呼叫 ntptime.settime()

  • 主機名稱必須相符。當用戶端傳入 server_hostname 時,它必須與憑證的 subjectAltName 相符(在較舊的堆疊上則是 CN),否則驗證會失敗。

  • 格式錯誤。複製到相機上的 PEM 檔案無法載入,請先轉換為 DER。

  • 憑證已過期。先前可運作、如今卻以 OSError 失敗的連線,可能只是憑證已過期,請檢查有效日期並視需要重新產生/重新部署。

  • Ed25519 金鑰會失敗。請使用 ECDSA P-256/P-384 或 RSA,而非 Ed25519。

  • 錯誤皆為 OSError。MicroPython 並未實作 ssl.SSLError;TLS 失敗(憑證無效、已過期、未知 CA、格式錯誤、交握失敗)都會以 OSError 的形式拋出。