Skip to content

15 · 设备配对与 Push

设备配对解决“如何把已有身份安全带到新设备”,Push 解决“App 不在线时如何最小泄露地唤醒它”。两者都把秘密和短期凭证从普通 Relay 事件中隔离:配对使用短命 sidecar relay + ECDH/SAS;Push 使用独立 gateway、opaque capability、generation 与 durable outbox。

1. NIP-AB 配对角色

text
Source device                    Target device
  has identity                       fresh install
      │                                   │
      ├─ QR: source pubkey/session/relay/version
      │                                   │
      └──── ephemeral pair relay ─────────┘
             encrypted state machine

QR payload 不直接放长期私钥;它提供建立会话所需公开/临时材料。双方做 ECDH + HKDF,显示六位 SAS,用户人工确认两端一致后才继续传输身份材料。

2. Pairing 状态机

PairingSession 区分 source/target,限制:

  • 消息必须按预期次序。
  • session/peer/transcript 一致。
  • 重复 event 去重。
  • 固定总超时与连接超时。
  • abort reason 可传播。
  • 完成/失败/Drop 时秘密 zeroize。

SAS 使用 transcript hash 和 constant-time compare,防时序泄漏与中间人替换部分握手内容。

3. Pair relay

buzz-pair-relay 是专用 ephemeral relay,不应承载普通社区事件:

  • 只允许 pairing kinds/严格 filters。
  • 通过 p tag 定向投递。
  • 连接约 120 秒超时。
  • 有短窗口限流与 payload bounds。
  • 会话结束后没有长期历史价值。

缩小协议面比在主 Relay 里加大量“if pairing”更容易审计。

4. Push 为什么独立 gateway

APNs .p8、team/key ID 等是高价值基础设施凭证。Buzz 把它们只交给 buzz-push-gateway

text
client encrypted lease
      │ kind 30350 / NIP-PL

Buzz Relay DB + matcher + wake outbox
      │ opaque capability / endpoint generation

Push Gateway + its own PostgreSQL
      │ sole APNs custody

APNs → device wake-up

普通 Relay 不需要看到 APNs token 明文,也不持有 provider signing key。

5. Lease 与 generation

Push lease 是 author-only、parameterized replaceable 事件。客户端更新 endpoint/filters 会产生新 generation:

  • Relay 只为当前 generation 匹配事件。
  • outbox job claim 带 claim ID/lease。
  • worker 真正发送前再次 revalidate community、endpoint、generation。
  • provider 报 token 无效时只 disable 精确 generation,不能误伤用户刚更新的新 endpoint。

这解决典型竞态:旧 job 在队列里等待期间,用户重新注册了设备。

6. Durable outbox

Push 不能使用 Redis best-effort fan-out,因为 App 离线时恰恰需要可靠唤醒。事件 commit 后 matcher 把 wake 写入 PostgreSQL outbox;worker 使用 FOR UPDATE SKIP LOCKED/claim lease 并行领取:

text
Pending → Claimed(generation, claim_id, expires)
        → Sent
        → Retry(next_attempt)
        → Disabled/Dead

崩溃 worker 的 claim 到期后可被重新领取;发送端必须幂等/容忍重复,因为网络超时时无法总判断 APNs 是否已接收。

7. Gateway 自己的权威数据库

Gateway 维护与 Relay 不同的表:加密 APNs token、delegation/grant、App Attest 状态、replay 与 quota。这样即使 Relay DB 泄露,也只得到 opaque capability;要实际推送还需 gateway 的加密材料与 provider credential。

8. App Attest 与授权

iOS 注册路径可用 App Attest 证明请求来自合法应用实例。delegation/grant 将“用户签名身份”映射到“可注册某 endpoint 的设备凭证”。Gateway 还做:

  • 请求防重放。
  • endpoint/token quota。
  • provider 错误分类与 backoff。
  • 只有确定 token 永久无效时禁用。

9. 最小泄露通知

Push payload 应只包含唤醒/opaque routing 信息,正文回到 App 后从 Relay 拉取并通过正常权限门。把私密消息全文放进 APNs 会扩大 Apple/锁屏/日志暴露面,也绕开事件读取权限变化。

10. 完成度

配对: core crypto/state machine、sidecar relay、CLI 与 Desktop/Mobile 接线基础存在。

Push 服务端: lease、matcher、outbox、claim/revalidate、独立 gateway、App Attest/provider 主链完整。

产品闭环: 仍依赖真实 APNs 凭证、gateway 独立数据库、客户端 entitlement/注册/delegation 与生产监控。根 README 的“Push pending”更像交付状态,不代表服务器代码为空。

11. 源码入口

独立源码研究笔记 · 非 Buzz 官方文档