安全与加密
Mailwake 的原生推送在你的哨站上加密,在配对的 iPhone 上解密。本文说明 Mailwake 1.0 的密钥、加密流程和数据边界,帮助你判断哪些数据由自己保管、哪些数据经过官方服务。数据处理与保存约定见隐私政策。
三条数据路径
邮件通知、正文阅读和服务身份分别走不同的路径:
| 功能 | 数据路径 | 内容处理位置 |
|---|---|---|
| 原生邮件通知 | 邮箱 → 哨站 → 推送中继服务 → 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
加密。该密钥与数据库共同构成可恢复的数据:请一起备份,并保护主机与备份的访问权限。拿到数据库和本地密钥的人可以解密这些配置。
配对如何建立信任
推送配对二维码包含哨站公钥、推送中继服务地址与环境、配对标识及五分钟有效的一次性凭证。App 展示哨站指纹供你核对;请使用站主提供的可信邀请,核对连接信息后再确认。
设备对配对同意签名,将同意与哨站、设备加密公钥、一次性凭证和有效期绑定。哨站验证这份证明,锁定设备身份与公钥,再完成推送中继服务上的配对登记。后续通知使用这份已确认的关系选择加密公钥和验签公钥。
管理邀请可以同时携带推送配对,但两者分别授权:原生推送配对、配置管理和正文阅读具有各自的权限范围。操作步骤见连接 App。
一条通知如何加密
哨站为一次加密生成临时 P-256 密钥对、32 字节随机 salt 和 12 字节随机 nonce,然后执行:
- 用临时私钥与目标设备的公钥进行 P-256 ECDH 密钥协商,得到共享秘密。
- 用 HKDF-SHA256 派生 256 位内容密钥,派生上下文绑定推送中继服务环境、配对 ID 和事件 ID。
- 用 AES-256-GCM 加密通知 JSON,使用同一上下文作为附加认证数据,产生密文及 128 位认证标签。
- 用哨站的 P-256 签名密钥和 SHA-256 对加密信封及上下文签名,再通过 HTTPS 提交给推送中继服务。
- 推送中继服务验证签名与载荷格式,将密文交给 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 原生通道;第三方服务的数据范围与预览选项见通知渠道。
Markdown · AGPL-3.0-only · Mailwake 贡献者