← 所有文章2026.10.17 · 雲端平台

檔案加密後怎麼換密鑰?Envelope Encryption 與 Key Rotation

用 DEK 加密資料,再以 KMS 裡的 KEK 保護 DEK。理解兩層密鑰後,才能安全輪替、遷移與淘汰舊 key。

結論先行

大型檔案通常不會直接拿 KMS 裡的 master key 加密。成熟的做法是使用兩層不同用途的密鑰:

  • DEK(Data Encryption Key):直接加密檔案或資料。
  • KEK(Key Encryption Key):只負責加密,也就是 wrap DEK;保存在 KMS 或 HSM 裡。
flowchart LR
  F[原始檔案] -->|DEK · AES-GCM| C[加密檔案]
  D[DEK] -->|KEK · KMS wrap| E[Encrypted DEK]
  K[KEK<br/>不離開 KMS] --> E

實際系統也不只是兩把固定的 key,而是少量 KEK 保護許多 DEK:

一把 KEK
├── 包裝 File A 的 DEK
├── 包裝 File B 的 DEK
└── 包裝 File C 的 DEK

Google Cloud 建議 DEK 在本地產生、以加密形式保存,並可依資料粒度使用不同 DEK;KEK 則集中保存在 KMS。Google Cloud Envelope Encryption

為什麼需要兩層?

如果直接用同一把 master key 加密所有檔案,會遇到幾個問題:

  • KMS encrypt API 通常只適合小型資料,不是大型檔案傳輸工具。
  • 每次讀寫整份檔案都必須經過 KMS,延遲與費用增加。
  • 更換 master key 時,可能需要解密並重新加密所有檔案。
  • 單一 key 的使用範圍過大,事件發生時影響面難以控制。

Envelope encryption 把大量資料的高速對稱加密交給 DEK,只讓 KMS 保護很小的 DEK。AWS 也建議用 data key 加密資料,並把 encrypted data key 與 ciphertext 一起保存;明文 data key 使用後應盡快從記憶體移除。AWS KMS Data Keys

寫入與讀取流程

加密檔案

  1. 產生隨機 DEK。
  2. 使用 DEK 和 authenticated encryption,例如 AES-256-GCM,加密檔案。
  3. 呼叫 KMS,以 KEK wrap DEK。
  4. 儲存 encrypted file、encrypted DEK 與必要 metadata。
  5. 清除記憶體中的 plaintext DEK。
{
  "objectId": "document-123",
  "ciphertextUri": "oss://secure/document-123.enc",
  "encryptedDek": "base64...",
  "kekId": "document-encryption-key",
  "kekVersion": "v3",
  "algorithm": "AES-256-GCM",
  "nonce": "base64...",
  "authTag": "base64...",
  "encryptionSchema": 1
}

解密檔案

  1. 從 metadata 取得 encrypted DEK 和 KEK 資訊。
  2. 將 encrypted DEK 交給 KMS unwrap。
  3. 使用暫時取得的 plaintext DEK 解密檔案。
  4. 驗證 authentication tag。
  5. 清除 plaintext DEK。

應用程式不需要,也不應該把 KEK 放在環境變數或設定檔裡。它只持有呼叫 KMS 的身分與最小權限。

Rotation 不等於重新加密所有檔案

密鑰輪替至少有三種不同情況。

一般週期性 rotation

KMS 為同一個邏輯 key 建立新的 key material version:

舊資料 → KEK v1 / v2 仍可解密
新資料 → 一律使用目前的 KEK v3

這通常不會重新加密既有檔案,也不會自動更換舊 DEK。AWS KMS rotation 會在解密時選擇正確的舊版本;Key ID 本身不必改變。AWS KMS Key Rotation

淘汰舊 KEK:Rewrap DEK

如果目標是讓所有資料不再依賴舊 KEK,不需要先動大型檔案。只要將每個 encrypted DEK 重新包裝:

flowchart LR
  O[Encrypted DEK<br/>old KEK] --> U[Unwrap]
  U --> D[DEK<br/>memory only]
  D --> W[Wrap with new KEK]
  W --> N[Encrypted DEK<br/>new KEK]
  F[Encrypted file] -. 不需變更 .-> F

在支援 re-encrypt/rewrap 的 KMS 中,轉換甚至可以不把 plaintext DEK 暴露給應用程式。這也是兩層密鑰最大的營運價值:輪替的是小型 key material,不是所有大型資料。

DEK 或演算法遭到影響

如果 DEK 本身已洩漏,單純 rewrap 沒有用。攻擊者已經取得真正能解密檔案的 key,因此必須:

  1. 產生新 DEK。
  2. 解密原始 ciphertext。
  3. 使用新 DEK 重新加密檔案。
  4. 用安全 KEK wrap 新 DEK。
  5. 淘汰舊 ciphertext 與 key material。

如果 KEK 疑似遭到入侵,也要依攻擊者是否可能取得 encrypted DEK、ciphertext 與備份,評估是否需要全面更換 DEK。AWS 官方也明確說明,KMS key rotation 不會修復 compromised data key。

安全的輪替流程

正式環境不能在建立新 key 後立刻刪除舊 key。比較安全的順序是:

1. 建立新的 KEK version
2. 新寫入全部改用新版本
3. 背景 rewrap 舊 encrypted DEK
4. 統計仍依賴舊版本的資料
5. 驗證讀取與備份還原
6. 保留舊 KEK 觀察
7. Disable 舊 KEK
8. 再次觀察與演練 rollback
9. 確認無依賴後才排程 destroy

Rewrap job 應具備 idempotency、checkpoint、retry、audit log 和安全的 metadata 更新。若檔案剛好同時被更新,可以用版本欄位或 compare-and-swap,避免 migration 把較新的 encrypted DEK 覆蓋掉。

最容易遺漏的是備份

即使 production 已全部改用 v3,舊 snapshot 可能仍依賴 v1:

Production data → KEK v3
Six-month-old backup → KEK v1

只要 backup 還需要被還原,就不能銷毀 v1。選擇只有三種:遷移備份、等它超過 retention period,或明確接受銷毀 key 後舊資料永久不可恢復。

Google Cloud 也警告,rotation 不會自動重新加密既有資料;在確認所有依賴消失以前銷毀舊 key version,可能造成永久資料遺失。Google Cloud Key Rotation

權限也應分層

成熟的 key management 不只處理演算法,也處理誰能做什麼:

  • 應用程式只能使用指定 KEK 執行 wrap/unwrap。
  • Security 管理者可以設定 rotation policy,但不能讀取業務資料。
  • 維運工作可以執行 migration,但不能匯出 KEK。
  • Disable 與 destroy 需要額外核准和等待期。
  • Generate、decrypt、rewrap、disable 與 destroy 都應留下 audit log。

如果 KMS 支援 encryption context/AAD,可以把 tenant、object type 或用途綁進密文,避免 key 在錯誤情境下被使用;但這些欄位可能出現在 audit log,因此不能放敏感資料。AWS KMS Encryption Context

實務決策表

狀況 處理方式
一般定期 rotation 新資料使用新 KEK version,保留舊版本解密
準備淘汰舊 KEK Rewrap DEK,不重新加密大檔案
更換 KMS 或 key hierarchy 舊 KEK unwrap,交由新 KEK wrap
DEK 洩漏 產生新 DEK,重新加密受影響資料
KEK 疑似洩漏 評估暴露範圍,必要時更換 DEK 並重加密
演算法不再安全 使用新演算法重新加密資料
希望資料永久不可恢復 銷毀對應 key,但先處理所有備份與依賴

最後的原則

Key rotation 不是每隔一段時間替換一個環境變數。完整的設計必須回答:哪些資料由哪個 DEK 加密、DEK 由哪個 KEK version 保護、舊版本還被哪些正式資料與備份依賴,以及何時能安全淘汰。

Envelope encryption 的價值,是把資料生命週期和 master key 生命週期分開。大部分輪替只需搬動 encrypted DEK;真正發生洩漏或演算法淘汰時,才支付重新加密大型資料的成本。