Safe Haven 签名密钥轮换,管理员手动更新哈希基准
什么是签名密钥轮换
安卓应用用证书签名。密钥轮换是指开发者替换了签名用的证书,原因可能是:
- 原密钥丢失 / 证书过期
- 安全合规要求
- 从自签名换成正式发布证书
- 从 F-Droid 重签名切回开发者原生签名(认领场景)
Safe Haven 怎么检测到密钥变更
首次扫描 APK 时,Safe Haven 把签名证书的 SHA-256 哈希存到应用条目的 signingKeyHash 字段。这个字段是签名锁定的基准值。
之后每次:
- 扫描管线处理新版本:提取 APK 签名哈希 → 和基准比对
- 上架后复扫管线:重新扫描已上架的 APK → 提取签名哈希 → 和基准比对
比对发现不一致 → Safe Haven 自动把 signing_key_changed 标志置为 true,应用条目在客户端详情页上会显示"签名变更"警示。
变更后会发生什么
签名密钥变更被检测到后:
- 应用条目在客户端和 Web 前端会展示警示标志(信任标志区的"签名锁定"会变暗)
- Safe Haven 的 统一 Poller 会暂停这个应用的自动同步(避免继续拉不同签名的版本)
- 开发者不能直接用新签名上传新版本——扫描管线比对签名基准会失败或直接拒绝
- 必须由管理员手动覆盖签名基准哈希
管理员怎么覆盖哈希
Safe Haven 后端有一个专用的 Admin 权限 endpoint 用于签名密钥哈希覆盖。流程:
开发者侧
- 在 GitHub Issues 或 Discord 上联系 Safe Haven 管理员,说明密钥轮换情况
- 提供以下信息:
- 应用包名
- 旧签名哈希(可以用 apksigner 从旧 APK 提取)
- 新签名哈希(从新 APK 提取)
- 轮换理由(密钥丢失 / 证书过期 / 认领切签名 / 其他)
- 提交证明材料:新 APK 的
apksigner verify --print-certs输出
管理员侧
- 审核开发者提供的信息(是否是合法轮换还是可疑变更)
- 调用 Admin endpoint 覆盖应用条目的
signingKeyHash:
- 旧哈希
- 新哈希
- 管理员填写的理由
- 覆盖成功 →
signing_key_changed标志自动清除 - 统一 Poller 恢复对该应用的同步
- 新版本可以正常提交
每次覆盖都会被审计
Safe Haven 后端有专门的签名密钥覆盖审计表。每次哈希覆盖操作都会记录:
| 记录项 | 说明 |
|---|---|
| 应用包名 | 被修改签名的应用 |
| 旧哈希 | 覆盖前的 signingKeyHash |
| 新哈希 | 覆盖后的 signingKeyHash |
| 覆盖时间 | Unix 时间戳 |
| 操作管理员 | 执行覆盖的管理员账号 |
| 理由 | 管理员填写的变更理由(自由文本) |
审计表对外不公开,但 Safe Haven 团队内部可以追溯每次签名密钥变更的操作历史。
轮换后对用户的影响
签名密钥轮换成功后,对用户有两个直接影响:
必须卸载重装
安卓系统只允许同签名覆盖安装。如果你设备上装的还是旧签名的版本,Safe Haven 推送来的新签名版本会被安卓拒绝覆盖。用户必须:
- 备份应用数据
- 卸载旧版本
- 从 Safe Haven 装新版本
客户端提示更新延迟
Safe Haven 的统一 Poller 在签名锁定被重置前可能会暂停该应用的自动同步,所以管理员处理完签名覆盖后,用户可能需要等几小时到一天才能在客户端看到新版本。
轮换完成后的自检
开发者轮换完成后,可以做以下自检:
- 用
apksigner verify --print-certs确认新 APK 的指纹和你提供给管理员的一致 - 在 store.colourswift.com 的开发者后台查看 signingKeyHash 字段是否已更新
- 在客户端或 Web 前端检查应用详情页的"签名锁定"标志是否恢复正常(不再变暗)
- 提交一个新版本 → 应该能正常过扫描管线
特殊场景:认领 F-Droid 来源应用时的密钥切换
认领 F-Droid 同步进来的应用时,密钥切换是认领流程的一部分:
- 开发者认领应用时提交自己的签名哈希(不是 Safe Haven 管理员手动覆盖,是认领 API 直接处理)
- Safe Haven 清除所有旧的 F-Droid 签名的版本记录
- 存入开发者的新签名哈希作为基准
- 自动同步切换到开发者自己的仓库
这个场景下的密钥切换不需要走管理员覆盖流程——认领流程本身就包含了签名哈希的更新操作。
不是密钥轮换的其他签名变更
理论上的坏情况:有人恶意替换了你的 APK,签名变了,但 Safe Haven 检测到了。这种情况和合法轮换的区别:
| 维度 | 合法轮换 | 恶意替换 |
|---|---|---|
| 你主动发起 | ✅ | ❌ |
| GitHub Release 有说明 | ✅(Release Notes) | ❌ |
| 只有一个新哈希 | ✅ | 可能多个 |
| 管理员审批 | 你主动联系,提供证明 | 管理员自己发现异常 |
Safe Haven 管理员会根据这些线索判断,不会轻易批准任何签名哈希覆盖请求。