# Proposal: Add File Encryption **Change ID:** `add-file-encryption` **Issue Reference:** `FEAT-010` (issues.md) **Status:** Draft **Author:** Claude **Date:** 2026-01-05 ## Summary 實作 AES-256 加密存儲功能,對機密等級專案的附件進行加密保護,並提供金鑰管理與輪換機制。 ## Motivation 半導體產業的設計文件、製程參數和良率報告屬於高度機密資料。目前系統的附件以明文形式儲存於 NAS,若發生以下情況可能導致資料外洩: - NAS 遭未授權存取 - 備份媒體遺失 - 儲存設備報廢未妥善處理 透過 AES-256 加密,即使檔案被取得也無法解讀內容,提供額外的安全層。 ## Scope ### In Scope - Backend: EncryptionKey model 和 key 管理 API - Backend: 加密服務(encrypt/decrypt) - Backend: 附件上傳時自動加密(依專案機密等級) - Backend: 附件下載時自動解密 - Backend: 金鑰輪換功能 - 稽核日誌:加密相關操作記錄 ### Out of Scope - 客戶端加密(End-to-End Encryption) - Hardware Security Module (HSM) 整合 - 現有檔案的批次加密遷移(需另案處理) ## Design Decisions ### 加密策略 | 專案機密等級 | 加密行為 | |-------------|---------| | public | 不加密 | | department | 不加密 | | confidential | 強制加密 | ### 金鑰管理 - 採用對稱金鑰加密(AES-256-GCM) - 每個金鑰有唯一 ID,儲存於資料庫 - 金鑰本身使用 Master Key 加密後存儲 - Master Key 從環境變數讀取,不存於資料庫 ### 加密流程 ``` 1. 上傳檔案 2. 檢查專案機密等級 3. 若為 confidential: a. 取得當前有效金鑰 b. 使用 AES-256-GCM 加密檔案 c. 儲存加密後的檔案 d. 記錄 encryption_key_id 4. 儲存 Attachment 記錄 ``` ### 解密流程 ``` 1. 請求下載檔案 2. 驗證存取權限 3. 若 is_encrypted = true: a. 取得 encryption_key_id 對應的金鑰 b. 解密檔案 c. 返回解密後的內容 4. 若 is_encrypted = false: a. 直接返回檔案 ``` ### 金鑰輪換 - 建立新金鑰並標記為 active - 舊金鑰標記為 inactive(但保留用於解密舊檔案) - 新上傳檔案使用新金鑰 - 可選:批次重新加密舊檔案(背景任務) ### API 設計 ``` # 金鑰管理 (Admin only) GET /api/admin/encryption-keys # 列出所有金鑰 POST /api/admin/encryption-keys # 建立新金鑰 POST /api/admin/encryption-keys/rotate # 金鑰輪換 DELETE /api/admin/encryption-keys/{id} # 停用金鑰(不刪除) # 附件加密狀態由系統自動處理,無需額外 API ``` ## Affected Specs | Spec | Change Type | |------|-------------| | document-management | MODIFIED (File Encryption requirement 實作細節) | ## Risks & Mitigations | Risk | Mitigation | |------|------------| | Master Key 遺失導致資料無法解密 | 提供 Master Key 備份指引,建議異地保存 | | 加密效能影響 | 使用串流加密避免大檔案記憶體問題 | | 金鑰輪換中斷 | 使用資料庫交易確保原子性 | ## Dependencies - Python cryptography 套件 - Master Key 環境變數配置