# 安全與加密

Mailwake 的原生推播在你的哨站上加密，在配對的 iPhone 上解密。本文說明 Mailwake 1.0 的金鑰、加密流程和資料邊界，幫助你判斷哪些資料由自己保管、哪些資料經過官方服務。資料處理與儲存約定見[隱私政策](../../privacy/)。

## 三條資料路徑

郵件通知、內文閱讀和服務身分分別走不同的路徑：

| 功能         | 資料路徑                                         | 內容處理位置                                               |
| ------------ | ------------------------------------------------ | ---------------------------------------------------------- |
| 原生郵件通知 | 信箱 → 哨站 → 推播中繼服務 → Apple APNs → iPhone | 哨站讀取郵件並加密通知，iPhone 驗證簽章、解密和展示        |
| 按需閱讀內文 | iPhone → 你的哨站 → 信箱，再沿原路返回           | 哨站解析內文，App 在當前閱讀會話中展示                     |
| 裝置與購買   | App ↔ 裝置與購買服務                            | 完成裝置登記和購買驗證；推播中繼服務在投遞前核對裝置與權益 |

你執行的哨站可以讀取其獲准存取的郵件。這裡的端到端加密範圍是 **哨站到配對裝置之間的原生通知內容**。信箱服務商、哨站主機和解密後的裝置各自處於能夠接觸明文的邊界內。

## 金鑰由誰保管

**哨站身分金鑰**用於簽章。哨站在本機生成 P-256 簽章金鑰，使用本機設定金鑰加密儲存；公鑰提供給配對裝置和推播中繼服務，用於核對來源。哨站的身分隨資料目錄保留，重啟後繼續使用。

**裝置身分使用兩把獨立的 P-256 金鑰**：簽章金鑰證明裝置身分與配對同意，金鑰協商私鑰用於解密通知。在支援 Secure Enclave 的裝置上，App 使用其中生成的金鑰；其他執行環境使用軟體金鑰。金鑰記錄透過共享 Keychain 提供給 App 和擴充功能，採用 `AfterFirstUnlockThisDeviceOnly` 存取級別，並關閉 iCloud Keychain 同步。裝置重啟後的首次解鎖是後臺讀鑰的前提。

哨站和推播中繼服務儲存裝置公鑰。裝置解密私鑰由裝置保管；官方服務和 APNs 不持有這把私鑰。

哨站另外使用資料目錄中的 `secret.key` 對信箱憑據等敏感設定進行 AES-256-GCM 加密。該金鑰與資料庫共同構成可恢復的資料：請一起[備份](backup.md)，並保護主機與備份的存取權限。拿到資料庫和本機金鑰的人可以解密這些設定。

## 配對如何建立信任

推播配對QR Code包含哨站公鑰、推播中繼服務地址與環境、配對標識及五分鐘有效的一次性憑證。App 展示哨站指紋供你核對；請使用站主提供的可信邀請，核對連線資訊後再確認。

裝置對配對同意簽章，將同意與哨站、裝置加密公鑰、一次性憑證和有效期綁定。哨站驗證這份證明，鎖定裝置身分與公鑰，再完成推播中繼服務上的配對登記。後續通知使用這份已確認的關係選擇加密公鑰和驗證簽章公鑰。

管理邀請可以同時攜帶推播配對，但兩者分別授權：原生推播配對、設定管理和內文閱讀具有各自的權限範圍。操作步驟見[連接 App](connect-app.md)。

## 一條通知如何加密

哨站為一次加密生成臨時 P-256 金鑰對、32 位元組隨機 salt 和 12 位元組隨機 nonce，然後執行：

1. 用臨時私鑰與目標裝置的公鑰進行 P-256 ECDH 金鑰協商，得到共享秘密。
2. 用 HKDF-SHA256 派生 256 位內容金鑰，派生上下文綁定推播中繼服務環境、配對 ID 和事件 ID。
3. 用 AES-256-GCM 加密通知 JSON，使用同一上下文作為附加認證資料，產生密文及 128 位認證標籤。
4. 用哨站的 P-256 簽章金鑰和 SHA-256 對加密信封及上下文簽章，再透過 HTTPS 提交給推播中繼服務。
5. 推播中繼服務驗證簽章與載荷格式，將密文交給 APNs。裝置先用配對時確認的哨站公鑰驗證簽章，再用自己的私鑰協商內容金鑰、驗證認證標籤並解密。

演算法標識為 `P256-HKDF-SHA256-A256GCM`。同一次投遞的重試複用已經生成的加密信封與事件標識；新的加密操作生成新的臨時金鑰和隨機值。普通通知由通知服務擴充功能處理，驗證碼即時動態由 Widget 擴充功能處理；即時動態同樣使用簽章密文，並將活動身分和生命週期欄位綁定到加密上下文。

加密通知包含信箱顯示名稱、資料夾、寄件者、主旨、收件時間，以及可選的驗證碼和郵件引用。完整內文透過下一節的獨立路徑讀取。驗證簽章或解密失敗時，裝置保留安全佔位提示，郵件明文只在驗證成功後展示。

## 內文透過 HTTPS 直接讀取

開啟內文時，App 向已確認的哨站 HTTPS 地址發起請求。哨站檢查裝置憑證、站主授予的內文權限和簽章郵件引用限定的資源範圍，再從信箱按需讀取內文與引用的內嵌圖片。內文讀取免費，推播配對本身不授予內文權限。

哨站清理 HTML，並提供可讀文字回退；App 控制遠端圖片載入。遠端圖片可能聯絡寄件者的伺服器，因此載入需要遵循 App 的圖片選項。普通附件不在這一內文讀取流程內。

哨站在請求記憶體中處理內文。回應使用 `Cache-Control: no-store`；App 停用 HTTP 快取並拒絕重新導向。首次讀取成功後，App 將內文與單封圖片授權另存到這台 iPhone，供離線和重新啟動後閱讀；檔案受 iOS 檔案保護並排除備份。通知刪除或到期時同步清除內文與圖片授權；移除哨站也會清除其已儲存內文，保留通知摘要。遠端圖片檔案保持暫時讀取，再次開啟可能需要連線。內文直接從哨站返回 App，官方服務不參與這次傳輸，診斷與記錄始終排除內文。

## 官方服務能看到什麼

| 參與方         | 為完成職責可處理的資料                                          |
| -------------- | --------------------------------------------------------------- |
| 你的哨站       | 信箱憑據、郵件明文、通知設定、配對公鑰及本機投遞記錄            |
| 推播中繼服務   | 哨站／裝置／配對標識、公鑰、APNs 令牌、加密信封、投遞時間與狀態 |
| 裝置與購買服務 | 服務身分、裝置與會話資訊、購買與權益，以及投遞診斷後設資料      |
| Apple APNs     | 推播令牌、路由與投遞資訊、通用提示及加密載荷                    |
| 你的 iPhone    | 裝置金鑰、解密後的通知和本機歷史，以及獲准讀取的內文            |

寄件者、主旨和驗證碼位於原生通知密文內；處理密文的中轉服務仍可觀察投遞關係、時間和載荷大小等資訊。運營投遞診斷使用標識、狀態、錯誤碼與時間，郵件內容繼續遵循上述加密邊界。各服務也會按其職責處理必要的網路資訊，詳見隱私政策。

## 本機記錄、撤銷與安全邊界

哨站的待投遞任務和管理員歷史具有獨立的儲存規則，本機歷史可能包含信箱與主旨摘要。App 解密後的通知歷史儲存在本機 App Group，受系統檔案資料保護，可設定保留期限並清空。內文使用上文說明的獨立受保護快取。

解除配對用於阻止該關係繼續投遞，撤銷內文或管理憑證用於終止相應存取。已經到達裝置並解密的內容需要在裝置上清理；撤銷關係不能遠端收回已經看到的內容。

這套設計依賴哨站主機、配對邀請和裝置的安全。它保護傳輸中的通知內容，無法消除已被控制的哨站或已解鎖裝置讀取明文的風險。當前協議使用裝置長期金鑰協商私鑰：如果該私鑰洩露，持有歷史密文的人可能解密舊通知，因此本方案不承諾針對接收方長期私鑰洩露的前向保密。

選擇 Bark、Pushover 或 Webhook 時，通知按對應管道的格式發給你設定的服務。上述原生推播加密協議僅適用於 Mailwake 原生通道；第三方服務的資料範圍與預覽選項見[通知管道](notifications.md)。
