安全模型
MimiKey 如何在服务器看不到任何明文的前提下保存、同步和授权使用你的数据,以及它能防什么、不能防什么。
零知识原则
MimiKey 把「账号」和「能解密」分开:账号只回答你是谁、你的库在哪、哪些设备属于你;真正解密数据所需的两样秘密——主密码和 Secret Key——只存在于你的设备上,从不发给服务器。
由此得到三条不变量,所有客户端(Mac、iOS、Web)和第三方授权都遵守:
- 条目在你的设备上加密后才上传,服务器只保存和转发密文。
- 服务器保存的任何东西(登录验证器、密钥包裹、令牌哈希)都不足以解密你的条目。
- 第三方应用拿到的永远是你在 MimiKey 自己的界面里逐次批准、并密封给该应用这一次授权的单条结果。
注意 零知识保护的是「诚实但被攻破的服务器」和「数据库泄露」这类场景。它不能保护已被恶意软件控制的设备,详见下文威胁模型。
服务器保存什么
| 类别 | 服务器保存 | 说明 |
|---|---|---|
| 账号 | 邮箱、账号状态、SRP 盐(16 字节)与验证器 | 验证器由主密码 + Secret Key 经 Argon2id 派生的材料计算,推不出主密码 |
| 条目 | 条目 ID、修订号、时间戳、加密信封(密文) | 标题、网址、用户名、密码、备注等全部字段都在密文里 |
| 同步 | 每库的变更日志(同样只有密文与修订号) | 冲突时原样返还,不自动合并 |
| 设备 | 设备 ID、名称、公钥、密钥版本、撤销状态 | 撤销后该设备的会话立即失效 |
| 共享 | 账号身份公钥、被密封的身份私钥、共享库密钥包裹、库钥指纹、成员权限 | 包裹只有收件人的身份私钥能打开 |
| 第三方授权 | client 信息、client_secret 哈希、授权码/令牌哈希、每次授权的审批公钥与 seal 公钥、请求元数据、密封后的结果与补丁 | 令牌、授权码、secret 一律只存 SHA-256 哈希 |
| 计费 | 套餐、订单、订阅记录 | 与加密数据无关 |
服务器永远不保存什么
- 主密码(任何形式,包括哈希)
- Secret Key
- 个人库的库钥、共享库的明文库钥
- 条目明文
- 账号身份私钥的明文
- 第三方应用的 seal 私钥与审批私钥(只在该应用安装的系统钥匙串里)
提示 服务器仍能观察到一些元数据:条目数量、密文长度、修改时间、设备与请求的时间线,以及第三方请求里接入方填写的提示信息(
reason、hint、prefill、fields)。这些字段是明文,接入方不得在其中放入任何凭据。
两秘密密钥派生(2SKD)
你的所有账号密钥都由两样秘密共同派生:
- 主密码:你记住的口令,长度 12–1024 字节。
- Secret Key:注册时在你设备上随机生成的 128 位密钥,以
PM-开头、26 个 Crockford Base32 字符显示。它只保存在你的设备和应急包里。
两者与账号盐一起经 Argon2id(64 MiB 内存、3 次迭代、1 条并行通道)派生,并按用途做域分隔,得到三份互不可推的材料:
| 材料 | 域 | 用途 |
|---|---|---|
| 登录材料 | password-manager/account-login/v1 | SRP 登录的口令输入,服务器只拿到由它算出的验证器 |
| 库钥 | password-manager/account-vault/v1 | 个人库条目的加密根密钥 |
| 身份材料 | password-manager/account-identity/v1 | 密封账号身份私钥,用于共享与第三方修改补丁 |
这意味着:
- 数据库泄露时,攻击者必须同时猜中主密码和 128 位 Secret Key,并为每次猜测付出 Argon2id 的代价,离线暴力破解不可行。
- 只有主密码不够:新设备首次登录必须输入 Secret Key。
- 找回账号需要 Secret Key:没有应急包时不存在任何找回路径,服务器也无法代算。主密码和 Secret Key 都丢失时,数据按设计不可恢复。
算法参数与域字符串的完整列表见加密细节。
SRP 登录
登录使用 SRP-6a(RFC 5054 2048 位群,SHA-256),账号标识为规范化(去空白、小写)后的邮箱:
- 客户端发送临时公钥
A,服务器返回盐与临时公钥B。 - 双方各自计算共享密钥;客户端发送证明
M1,服务器验证后返回证明M2,客户端再验证服务器。 - 成功后服务器签发账号会话令牌(30 分钟有效)。
主密码、Secret Key 与登录材料都不会出现在网络上;被动窃听或重放握手都拿不到可用的口令。登录成功后,客户端在本地用同样的两样秘密重新派生库钥与身份材料,解密条目。
注意 SRP 的验证器一旦泄露,仍可作为离线猜测的目标(代价由 2SKD 决定)。更强的 OPAQUE 协议在路线图中,尚未实现。
设备与共享身份
设备登记。 每台登录过的设备在服务器登记自己的公钥。你可以在设备列表中随时撤销某台设备:其现有会话立即失效,之后的挑战登录也被拒绝。账号的最后一台活跃设备不能被撤销。
账号身份密钥。 每个账号有一对 X25519 身份密钥。公钥公开存放;私钥用身份材料密封后存服务器,任何完成 SRP 登录的客户端都能在本地解封。身份指纹为公钥 SHA-256 的前 8 字节(十六进制),可用于核对。
共享库。 个人库的库钥由 2SKD 派生、从不分发;共享库使用随机生成的 32 字节库钥,并以 sealed box 的方式逐个成员包裹给其身份公钥。服务器只保存包裹密文和库钥指纹。
移除成员。 库主的客户端会先用新随机库钥重新加密全部条目,再给剩余成员重新分发包裹,最后才在服务器上删除成员。被移除的成员从此无法同步新密文,但其在成员期间已经取得或导出的旧数据仍可被旧钥打开——这是端到端加密的固有边界。
本机保护
| 保护 | Mac | iOS | Web |
|---|---|---|---|
| 闲置自动锁定 | 5 分钟无操作后清除内存密钥 | 5 分钟无操作后锁定 | 5 分钟无操作后释放内存密钥 |
| 剪贴板 | 复制由原生进程完成,30 秒后或锁定时清除(仅当剪贴板内容仍是本次复制的内容) | 30 秒后过期,标记为仅本机(不经通用剪贴板同步) | 写入系统剪贴板,不会自动清除 |
| 生物识别解锁 | Touch ID:Secure Enclave 中不可导出的密钥保护派生材料 | 面容 ID / 触控 ID:钥匙串条目受生物识别门控 | 不支持 |
| Secret Key 存放 | 应用本地存储,退出登录时清除 | 系统钥匙串(仅本机、不同步) | 浏览器本地存储,退出登录时清除 |
iOS 生物识别。 主密码默认不保存在设备上。只有当你显式开启生物识别解锁时,主密码才以 biometryCurrentSet 访问控制写入钥匙串,且要求设备设置了锁屏密码;新增或删除指纹/面容后该条目自动失效,需要重新用主密码解锁并开启。
Mac Touch ID。 开启后,Mac 在 Secure Enclave 中生成一把不可导出、需要生物识别才能使用的密钥,用它保护一把随机包裹密钥,再用包裹密钥密封 2SKD 的三份派生结果。记录文件仅本人可读,不包含主密码或 Secret Key;密封数据绑定服务器地址与账号邮箱,不能挪到其他账号。主密码修改或账号找回后旧记录自动失效。
注意 剪贴板历史、云剪贴板以及其他进程在清除前已经读到的副本都无法被撤回;剪贴板清除不是保密隔离手段。
第三方授权的保证
第三方应用通过 MimiKey SDK 接入(见开发者概览)。平台对你提供以下保证:
- 决策界面只在 MimiKey 里。 同意、选条目、读取、新建、修改的批准卡全部由 MimiKey 自己的进程渲染。接入方 App 里只允许出现「即将打开 MimiKey」这类无决策提示,它无法替你点按钮、盖假卡或读取卡上的内容。
- 只给你批准的那一条。 接入方看不到条目列表;每次结果都是单条,并密封给该应用这一次安装、这一次授权专属的 seal 公钥,服务器只见密文。
- 新建与修改的明文不经接入方。 新建条目的密码在 MimiKey 的安全卡上输入;修改请求的新值由 SDK 密封给你的账号身份公钥,只有你已解锁的设备能打开。
- 令牌被盗也不够。 每个数据调用都必须带上该授权专属审批私钥的 Ed25519 签名,时间窗 ±300 秒,nonce 单次有效;审批私钥只在该应用安装的系统钥匙串里。
- 回调不带数据。 跳回接入方的 URL 只含
code、request_id、state、status;即使自定义 scheme 被其他 App 抢注,也拿不到任何密文或明文。 - 随时撤销、即时生效。 你可以在 MimiKey「第三方授权」里撤销任一授权;平台运营方也可停用违规接入方,其全部授权与令牌立即失效。
注意 一旦你批准把某条条目交给接入方,该应用就持有了这条明文。MimiKey 无法限制接入方之后如何使用它。只授权你信任的应用。
威胁模型摘要
MimiKey 防御的场景
| 场景 | 防御方式 |
|---|---|
| 服务器被入侵或数据库泄露 | 只有密文、验证器和哈希;离线破解需同时猜中主密码与 Secret Key,并承担 Argon2id 代价 |
| 网络窃听、中间人重放 | TLS;SRP 不传输口令;第三方调用带时间戳、nonce 与签名 |
| 第三方访问令牌泄露 | 没有审批私钥签名无法调用;access token 1 小时过期 |
| refresh token 被盗用 | 每次续期轮换;已作废的 refresh token 再次出现会立即吊销整个令牌家族 |
| 授权码被截获 | 授权码 10 分钟、单次有效;公共客户端强制 PKCE(S256) |
| 回调 scheme 被抢注 | 回调不携带任何数据,结果只能用该安装的私钥取回并解开 |
| 恶意或被攻破的接入方 App | 看不到其他条目;无法伪造批准卡;每次读取按你的策略逐次批准 |
| 设备丢失 | 自动锁定;远程撤销设备;钥匙串条目仅本机、不同步 |
MimiKey 不能防御的场景
- 已被攻破的设备。 恶意软件、同一用户下的其他进程、管理员权限的程序可以读取内存、本地存储中的 Secret Key、键盘输入或屏幕内容。
- 被篡改的 Web 前端。 如果服务器被攻破并下发恶意网页脚本,它可以在你使用 Web 端时读取浏览器本地存储中的 Secret Key 并截获你输入的主密码。对安全要求高的场景请使用 Mac 或 iOS 原生应用。
- 弱主密码 + Secret Key 同时泄露。 两样秘密都落入攻击者手中时,保护仅剩主密码强度。
- 两样秘密都遗忘。 数据按设计不可恢复,没有后门。
- 已经交出的数据。 你批准给第三方的结果、被移除成员此前取得的数据、剪贴板历史,都无法收回。
- 元数据。 服务器能看到条目数量、大小、时间和第三方请求的提示文字。
- 恶意服务器删除或回放旧密文。 目前没有防回滚账本;服务器无法读取或伪造条目内容,但可以拒绝服务、隐藏条目或回放旧版本密文。
- 量子计算。 当前使用的 X25519 / Ed25519 不具备抗量子能力。
审计状态
MimiKey 目前处于内部测试阶段,尚未经过独立第三方安全审计。
我们已经做到的:
- 加密核心使用成熟的开源实现(RustCrypto 的 Argon2、XChaCha20-Poly1305、HKDF、SRP,以及 curve25519-dalek / ed25519-dalek),并以
zeroize清理内存中的密钥。 - Rust、Swift 与 JavaScript 实现之间以公开测试向量做跨语言互验(见加密细节)。
- 服务端每个关键流程都有隔离环境下的端到端验收脚本。
在独立审计完成之前,我们建议不要把银行、主邮箱、Apple ID 等最要紧的账号作为唯一副本存放在 MimiKey 中。尚未完成的工作包括:OPAQUE 登录、防回滚账本、抗量子密钥交换与独立外部审计。