具代表性的面試主題

程式設計面試:如何用 Go 1.26 crypto/hpke 設計可輪換的信封加密?

程式題困難
Offer.cc 編輯團隊發佈 更新

題幹

請用 Go 1.26 的 crypto/hpke 為多租戶設定服務設計信封加密。要求支援金鑰輪換、舊密文解密、租戶隔離與竄改偵測;請說明模式選擇、上下文綁定、金鑰生命週期與測試。

題幹與適用場景

多租戶設定服務要加密資料庫中的敏感值。每個租戶有獨立邏輯金鑰,平台需要輪換根金鑰、繼續讀取舊密文,並能偵測密文被替換或跨租戶複製。請使用 Go 1.26 crypto/hpke 設計信封格式、加密/解密流程、金鑰版本、上下文綁定與遷移策略。核心考察密碼學 API 的正確組合與生命週期設計,因此歸為 coding

面試官考察點

第一,能否理解 HPKE 的 KEM、KDF、AEAD 分工,並區分公鑰封裝與對稱資料加密。

第二,能否選擇 Base、PSK 或 Auth 模式,說明認證金鑰與機密性金鑰的責任邊界。

第三,能否把租戶、用途、演算法套件與版本綁定到 info 或 AAD,防止跨上下文解密。

第四,能否設計金鑰輪換、舊版本讀取、撤銷與密文重加密,不把版本號當作秘密。

第五,能否用竄改、重放、隨機數、失敗訊息與互通性測試驗證實作。

回答前需要澄清的問題

  • 設定服務只需機密性,還是也需要傳送方認證?
  • 接收者公鑰由誰託管,是否有 KMS/HSM 與稽核要求?
  • 輪換後舊密文保留多久,是否需要背景重加密?
  • 租戶上下文與設定鍵是否屬於可公開的關聯資料?
  • 是否需要跨語言解密或離線復原?
  • 失敗時要區分金鑰不存在、版本不支援與認證失敗嗎?

30 秒回答框架

「我先固定 RFC 9180 套件與 Go 1.26 版本。服務端為每個租戶保存接收者私鑰,應用用公鑰做 HPKE 封裝;密文記錄套件、key version、租戶與用途元資料,真正的租戶/用途綁定放進 info 與 AEAD AAD。解密按版本讀取舊私鑰,輪換後新寫入使用新版本,背景非同步重加密。若需要傳送方認證再選 Auth 模式;否則不偽造認證語義。測試涵蓋竄改、跨租戶、重放、隨機性、舊版本與跨語言向量。」

分步驟深入解答

第一步:劃分信封加密層

HPKE 透過 KEM 建立共享金鑰,再由 KDF 推導金鑰,AEAD 加密訊息。信封記錄封裝公鑰材料、演算法套件、key version、nonce/序列化密文與公開元資料;根私鑰與接收者私鑰留在 KMS/HSM,不能寫入密文或應用日誌。

第二步:選擇模式與身分語義

Base 模式提供接收者公鑰加密但不認證傳送方;PSK 模式額外要求預共享金鑰;Auth 模式用傳送方金鑰證明來源。不要因為有平台登入身分就宣稱 HPKE 已認證傳送方,登入授權與密碼學模式是不同層。

第三步:定義上下文綁定

info 綁定協定、服務、版本與用途;AAD 綁定租戶 ID、設定鍵、記錄版本等需要完整性保護的元資料。解密時重新計算相同輸入,任何租戶、用途或版本替換都會讓 AEAD 驗證失敗。

text
envelope = suite_id | key_version | encapsulated_key | aad_fields | ciphertext
info = "config-envelope/v1" | tenant_scope | purpose
aad = tenant_id | config_key | record_version

第四步:設計金鑰生命週期

每個 key version 有產生時間、狀態、允許解密範圍與銷毀策略。輪換先發布新公鑰,再切換寫入版本;讀取按 envelope 版本選擇舊私鑰。舊版本進入唯讀窗口,完成重加密與稽核確認後才能撤銷,避免先刪金鑰造成不可復原資料遺失。

第五步:處理重放與序列化

AEAD 能偵測竄改,不會自動阻止把合法舊密文重新寫回。若設定有版本或單調序列,解密後由業務層檢查 expected version;封裝格式使用明確長度與版本欄位,拒絕未知套件、截斷資料與重複欄位。

第六步:設計錯誤邊界

對外可統一回傳「無法解密」,內部稽核記錄結構化原因與 key version,但不能記錄私鑰、明文或完整密文。區分金鑰不存在、格式不支援與認證失敗有助於維運;對不可信呼叫者要避免透過錯誤差異洩露租戶或金鑰存在性。

第七步:建立測試與遷移

測試固定 RFC 向量、隨機性、竄改單一位元組、跨租戶 AAD、舊版本讀取、輪換並發、撤銷後失敗與大訊息分塊。跨語言場景使用共享序列化與測試向量;Go 1.26 之前服務透過相容封裝或升級門禁接入,不把實驗 API 混入生產。

高品質示範回答

「我把 HPKE 當作封裝層:KEM/KDF 建立並推導共享金鑰,AEAD 保護設定明文。信封包含套件、key version、封裝材料與密文;租戶、用途、設定鍵與記錄版本綁定到 info/AAD,防止跨租戶複製。Base 模式只提供接收者機密性,需要傳送方證明時才選 Auth 或上層簽章。輪換採用新版本先寫、舊版本唯讀、背景重加密、確認後撤銷。AEAD 不防重放,所以業務層檢查版本。測試涵蓋竄改、舊版本、撤銷、錯誤訊息與跨語言向量,私鑰只在 KMS/HSM 中。」

常見錯誤

  • 把 Base 模式當傳送方認證 → 接收者無法證明傳送者身分 → 選擇 Auth 或額外簽章。
  • 只把租戶寫在明文元資料 → 攻擊者可跨租戶替換 → 綁定到 info/AAD 並驗證。
  • 輪換後立即刪除舊金鑰 → 歷史資料無法讀取 → 先唯讀相容與重加密,再撤銷。
  • 認為 AEAD 自動防重放 → 合法舊密文仍可被重新提交 → 使用業務版本或序列檢查。
  • 把私鑰放進設定或日誌 → 加密邊界被破壞 → 使用 KMS/HSM 與最小權限。
  • 自訂無版本二進位格式 → 未來無法遷移與拒絕未知套件 → 明確版本、長度與套件欄位。
  • 暴露詳細解密錯誤 → 洩露租戶或金鑰存在性 → 外部統一、內部稽核。
  • 只測成功路徑 → 竄改與舊版本問題留到生產 → 加入向量、跨上下文與撤銷測試。

追問及應對

追問一:為什麼不用直接 RSA 或 ECDH 加密全部明文?

HPKE 明確組合 KEM、KDF 與 AEAD,適合封裝對稱會話金鑰並處理大訊息;直接用公鑰演算法加密任意明文容易遇到長度、隨機性與模式誤用問題。

追問二:何時選擇 Auth 模式?

當接收者需要密碼學證明某個已知傳送方金鑰參與加密時選擇 Auth;只有接收者機密性需求時不應加入未管理的認證金鑰。

追問三:info 與 AAD 有什麼差別?

info 參與金鑰推導並定義協定上下文;AAD 不加密但由 AEAD 完整性保護,適合綁定隨信封傳輸且解密時必須一致的元資料。

追問四:如何安全重加密?

讀取舊版本並在同一交易或可重試工作流中寫入新版本,保留冪等標記;只有新密文通過解密回讀與稽核校驗後,才推進舊金鑰撤銷。

追問五:如何防止密文替換到另一筆記錄?

把租戶、設定鍵、記錄版本與用途放入 AAD,並在讀取時使用資料庫目前值重建 AAD;替換後認證標籤不匹配,解密失敗。

追問六:HPKE 是否提供前向保密?

具體性質取決於金鑰生命週期與模式。靜態接收者私鑰長期保留時,歷史密文的保護取決於該私鑰;需要更強前向保密時要設計臨時金鑰、輪換、銷毀與協定級會話策略,不能只看 API 名稱。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具