跳轉到

加密架構

券商憑證是平台中最敏感的資料。它們直接授予對持有真實資金的交易帳戶的存取權限。這些憑證必須在靜態儲存、傳輸過程和處理期間全程加密。私鑰永遠不離開硬體。

4pass 實作了三層加密金鑰層級,並具備每位使用者隔離機制,確保一位使用者資料的外洩不會擴散到其他使用者。


加密金鑰層級

flowchart TB subgraph HSM["AWS KMS HSM (FIPS 140-2 Level 3)"] MASTER["主金鑰<br/>(RSA-4096 或 AES-256)<br/>不可匯出"] end subgraph Server["應用程式伺服器"] ACCOUNT_KEY["每帳戶加密金鑰<br/>32 位元組 AES-256 金鑰<br/>(每個交易帳戶獨立)"] DECRYPT["已解密憑證<br/>(僅存於記憶體,不持久化)"] end subgraph DB["PostgreSQL"] ENC_ACCOUNT_KEY["加密的帳戶金鑰<br/>(由主金鑰封裝)"] ENC_CREDS["加密的憑證<br/>AES-256-GCM 密文<br/>+ 12 位元組 Nonce + GCM 標籤"] end MASTER -->|"信封解密<br/>(KMS API 呼叫)"| ACCOUNT_KEY ENC_ACCOUNT_KEY -->|"以加密方式儲存"| ACCOUNT_KEY ACCOUNT_KEY -->|"AES-256-GCM 解密"| DECRYPT ENC_CREDS -->|"從資料庫讀取"| DECRYPT

三層保護:

層級 金鑰 保護方式 用途
第一層 KMS 主金鑰 AWS HSM 硬體(不可匯出) 加密/解密每帳戶金鑰
第二層 每帳戶金鑰 以主金鑰加密,儲存於資料庫 加密/解密實際憑證
第三層 憑證密文 以每帳戶金鑰加密 靜態儲存的券商 API 金鑰和密鑰

為什麼需要三層?

如果資料庫被入侵,攻擊者取得第三層(密文)和第二層(加密的帳戶金鑰),但若無第一層(HSM 中的 KMS 主金鑰)則無法解密任何資料。如果應用程式記憶體被傾印,攻擊者取得一位使用者的已解密憑證,但無法取得其他使用者的——每個帳戶都有獨立的金鑰。


前端到後端加密

當使用者透過控制面板提交券商憑證時,混合 RSA-4096 + AES-256-GCM 加密方案提供端對端保護——即使 TLS 被中間人代理或 CDN 設定錯誤所攻破。

sequenceDiagram participant Browser as 瀏覽器(Web Crypto API) participant API as FastAPI participant KMS as AWS KMS HSM participant DB as PostgreSQL Browser->>API: 1. GET /auth/encryption-key API->>KMS: GetPublicKey(key_id) KMS-->>API: RSA-4096 公鑰(PEM) API-->>Browser: 公鑰(已快取) Note over Browser: 2. 產生隨機 AES-256 金鑰<br/>crypto.subtle.generateKey("AES-GCM", 256) Note over Browser: 3. 以 AES-GCM 加密憑證<br/>每次操作隨機產生 12 位元組 IV Note over Browser: 4. 以 RSA-OAEP-256 加密 AES 金鑰<br/>crypto.subtle.encrypt("RSA-OAEP", publicKey, aesKey) Browser->>API: 5. POST /trading/accounts<br/>{encrypted_key, encrypted_data, iv, tag} API->>KMS: 6. Decrypt(encrypted_key)<br/>私鑰留在 HSM 中 KMS-->>API: 已解密的 AES-256 金鑰 API->>API: 7. AES-GCM 解密憑證<br/>使用已解密的 AES 金鑰 + IV + 標籤 API->>API: 8. 以每帳戶儲存金鑰<br/>重新加密(AES-256-GCM) API->>DB: 9. 儲存加密憑證<br/>(Nonce + 密文 + GCM 標籤) Note over API: AES 金鑰和明文憑證<br/>僅存於記憶體中,隨後被垃圾回收

此流程的關鍵安全特性:

  • 前向保密 (Forward Secrecy) —— 每次憑證提交都會產生全新的隨機 AES-256 金鑰。攻擊一個請求的金鑰不會解密其他請求。
  • HSM 支援的解密 —— RSA-4096 私鑰永遠不離開 KMS HSM。步驟 6 是一個 KMS API 呼叫;明文 AES 金鑰會返回給應用程式,但私鑰始終留在硬體中。
  • Web Crypto API —— 瀏覽器使用原生 crypto.subtle API(非 JavaScript 函式庫),在安全上下文中執行,且能抵抗側通道攻擊 (Side-Channel Attack)。
  • 傳輸過程中無明文 —— 即使 HTTPS 已加密連線,憑證酬載仍獨立加密。TLS 攔截代理只能看到密文。

儲存加密(每位使用者 AES-256-GCM)

當憑證到達伺服器後,會以每帳戶金鑰重新加密,儲存於 PostgreSQL 中。

屬性
演算法 AES-256-GCM(認證加密)
金鑰大小 每個交易帳戶 32 位元組(256 位元)
Nonce (IV) 12 位元組(96 位元),每次加密操作隨機產生
認證 GCM 標籤提供完整性 + 機密性
金鑰隔離 每個 TradingAccount 都有獨立的加密金鑰
金鑰儲存 帳戶金鑰以主金鑰加密,儲存在 encrypted_key 資料庫欄位
加密版本 版本 2(目前);版本 1(Fernet/AES-128-CBC)用於舊有資料

資料庫欄位格式:

┌──────────┬────────────────────────┬──────────┐
│ 12-byte  │     Variable-length    │ 16-byte  │
│  Nonce   │      Ciphertext        │ GCM Tag  │
└──────────┴────────────────────────┴──────────┘
         Base64-encoded, stored as TEXT

Nonce 唯一性

每次加密操作都使用 os.urandom(12) 產生 12 位元組的隨機 Nonce。在 AES-GCM 中使用相同金鑰重複使用 Nonce 會完全破壞加密方案的安全性。隨機產生確保這不會發生(碰撞機率:每對 2^-48)。


主金鑰管理

保護每帳戶金鑰的主金鑰有兩種模式,根據 USE_AWS_KMS 環境變數自動選擇:

屬性
金鑰類型 KMS 管理的 AES-256 對稱金鑰
信封加密 KMS 加密每帳戶金鑰;應用程式使用明文資料金鑰
HSM 支援 FIPS 140-2 Level 3 硬體安全模組
稽核 所有金鑰操作記錄於 AWS CloudTrail
輪替 KMS 自動金鑰輪替(每年)
金鑰 ID AWS_KMS_KEY_ID 環境變數
區域 AWS_REGION / AWS_DEFAULT_REGION(預設:ap-southeast-1
Encrypt account key:
  KMS.Encrypt(plaintext=account_key, key_id=master_key)
    → encrypted_account_key (stored in DB)

Decrypt account key:
  KMS.Decrypt(ciphertext=encrypted_account_key)
    → plaintext account_key (in memory only)
屬性
金鑰類型 ENCRYPTION_KEY 環境變數衍生的 Fernet 對稱金鑰
衍生方式 PBKDF2-HMAC-SHA256,100,000 次迭代
鹽值 可透過 KEY_DERIVATION_SALT 設定
用途 僅用於本地開發和測試
PBKDF2(ENCRYPTION_KEY, salt, iterations=100000, hash=SHA256)
  → 32-byte Fernet key
  → Encrypt/decrypt per-account keys locally

自動模式選擇

應用程式根據 USE_AWS_KMS=true|false 自動選擇 KMS 或本地模式。在開發和正式環境之間切換不需要修改程式碼——只需更改環境變數。


加密版本控管

4pass 支援兩個加密版本,並具備自動前向遷移機制:

版本 演算法 金鑰大小 狀態 引入時間
v1 Fernet (AES-128-CBC + HMAC-SHA256) 128 位元 舊版 初始發佈
v2 AES-256-GCM 256 位元 目前(預設) 安全性升級

讀取時自動升級:

flowchart TB READ["讀取加密憑證"] --> CHECK{"版本?"} CHECK -->|v1| DECRYPT_V1["以 Fernet 解密"] CHECK -->|v2| DECRYPT_V2["以 AES-256-GCM 解密"] DECRYPT_V1 --> REENCRYPT["重新加密為 v2"] REENCRYPT --> SAVE["儲存升級後的密文"] DECRYPT_V2 --> USE["回傳明文"] SAVE --> USE
  • 現有 v1 資料在下次讀取時會被解密並透明地重新加密為 v2
  • 新資料一律使用 v2 (AES-256-GCM)
  • 維持向後相容性——兩個版本都可以無限期解密
  • 版本位元組前置於密文前,為未來的演算法升級預留空間

安全特性總覽

特性 機制 保證
前向保密 每次前端請求使用獨立的 AES-256 金鑰 攻擊一次提交不會解密其他提交
每位使用者隔離 每個交易帳戶使用獨立的 32 位元組金鑰 攻擊一個帳戶金鑰只影響該帳戶
HSM 支援 RSA-4096 私鑰存放於 KMS FIPS 140-2 L3 硬體中 私鑰永遠不存在於軟體記憶體中
認證加密 AES-256-GCM 搭配 128 位元認證標籤 竄改會在解密前被偵測並拒絕
靜態無明文 憑證在寫入資料庫前加密 資料庫傾印只會顯示密文
傳輸中無明文 RSA+AES 混合加密加上 HTTPS 雙層加密——TLS 失效也不會暴露憑證
稽核軌跡 KMS 操作記錄於 CloudTrail 所有解密事件可追蹤且可告警
金鑰輪替 KMS 自動年度輪替 + 版本遷移 無停機時間的前向安全性

攻擊者需要什麼

要解密單一使用者的券商憑證,攻擊者必須同時擁有:

  1. 資料庫存取權限(取得加密的憑證和加密的帳戶金鑰)
  2. KMS Decrypt 權限(使用主金鑰解封帳戶金鑰)
  3. 特定的帳戶金鑰(使用 AES-256-GCM 解密憑證)

僅攻破其中任何一項都無法揭露任何資訊