For the complete documentation index, see llms.txt. This page is also available as Markdown.

iOS 伴侣应用

通过一个端到端加密隧道,将 iOS 伴侣应用与桌面端 OpenHuman 配对,并通过二维码扫描完成。

iOS Companion 让你可以用手机连接桌面端的 OpenHuman:你在桌面上扫描显示的二维码,两台设备协商出一把共享密钥,此后手机便通过加密通道与桌面核心通信。

桌面核心始终是事实来源。手机只是一个轻客户端。它不运行自己的代理,而是把请求转发给核心并渲染结果。


它是什么

配对由 Rust devices 域在核心中进行协调。核心会向 tinyhumans 后端的 tunnel:* Socket.IO 中继注册一个配对通道,生成一对新的 X25519 密钥对,并渲染一个二维码。手机扫描后,生成 自己的 X25519 密钥对,并通过同一个中继连接回去。后端是一个 盲转发器:它转发不透明的数据帧,且从不看到明文。

配对完成后,该设备会显示在 设置 → 设备 中,旁边带有在线/离线状态点,并且可随时撤销。


通过二维码配对

桌面核心                         后端中继              iOS 应用
     |                                     |                        |
     |-- devices_create_pairing RPC        |                        |
     |-- tunnel:register ----------------->|                        |
     |<-- channel_id, expires_at ----------|                        |
     |-- generate X25519 keypair           |                        |
     |-- tunnel:connect (role: core) ----->|                        |
     |                                     |                        |
     |   显示二维码:                        |                        |
     |   cid, pt, cpk, rpc?, exp           |                        |
     |.................. 扫描二维码 ......................>            |
     |                                     |   生成设备的          |
     |                                     |   X25519 密钥对        |
     |                                     |<-- tunnel:connect ------|
     |                                     |    (role: client)       |
     |<------ tunnel:frame (handshake) ----|------------------------|
     |-- X25519 DH + derive session keys   |                        |
     |-- persist PairedDevice              |                        |
     |-- publish DevicePaired event        |                        |
     |   设备出现在 Devices 列表中        |                        |

二维码载荷(作为一个 openhuman://pair?... 深度链接承载)包含通道 ID(cid)、一次性配对令牌(pt)、核心的公钥(cpk)、可选的局域网 URL(rpc)以及过期时间(exp)。配对令牌只能使用一次,在后端落盘时会进行哈希处理;一旦 exp 已过,客户端就会拒绝该二维码(后端会强制执行真实的约 10 分钟 TTL)。


端到端隧道

机密性和完整性完全由两端负责。具体原语位于 src/openhuman/security/devices/crypto.rs:

  • 密钥协商: X25519 Diffie-Hellman。双方各自拥有一对长期静态密钥对(核心的密钥对会显示在二维码中;设备的密钥对在扫描时生成),另外每个会话还会生成一对临时密钥对,以提供前向保密。

  • 会话密钥派生:ikm = static_dh || eph_dh进行 HKDF-SHA256,并使用 client_eph_pub || server_eph_pub作为盐。随后用不同的 info 标签扩展出两把 单向的 32 字节子密钥(openhuman-tunnel/v1/c2s 以及 openhuman-tunnel/v1/s2c),因此一端封装的帧绝不可能使用它自己的开启端解密(从而消除了跨方向反射攻击这一类问题)。

  • 帧加密: XChaCha20-Poly1305(AEAD,192 位 nonce)。线协议格式为 version(0x02) || nonce(24) || ciphertext+tag,每个帧使用随机 nonce。

  • 重放保护: 针对每个开启端维护最近 128 个 nonce 的滑动窗口。

静态 DH 通过二维码来源来认证对端;临时 DH 则意味着即使之后静态密钥泄露,也无法解密过去的流量。旧版单密钥 version=0x01 帧格式会以明确的“需要重新配对”错误被拒绝,因此升级后双方必须重新配对。外发帧大小上限为 64 KB。


传输策略

手机可以通过三种方式连接到核心。 TransportManager (app/src/services/transport/)会从已保存的 ConnectionProfile中选择一种;对于已配对设备,它会 让局域网与隧道同时竞争 (2 秒局域网超时),并使用先响应 openhuman.ping 的那个。

策略
使用场景
权衡

局域网 HTTP (LanHttpTransport)

直接通过 HTTP 连接到核心的局域网 rpc_url

手机和桌面处于同一网络

速度最快,延迟最低。需要在同一局域网内;这一层不加密(依赖本地网络信任)。

隧道 (TunnelTransport)

通过后端 Socket.IO 中继传输端到端加密帧

任何可联网的地方;默认回退方案

可跨网络工作;端到端使用 X25519 + XChaCha20-Poly1305。延迟更高(经由中继);依赖后端可用性。

云端 HTTP (CloudHttpTransport)

通过云端托管的核心端点进行 HTTP 访问

配置文件 kind: "cloud",当局域网和隧道都不可用时

可从任何地方访问;依赖托管核心及其自身认证。


设备管理与撤销

配对设备由核心持久化到 SQLite({workspace_dir}/devices/devices.db,表 paired_devices):通道 ID、标签、设备公钥、核心会话令牌的 SHA-256 哈希以及时间戳。核心的 X25519 私钥在静态存储时会被加密保存(通过 OS keyring SecretStore)因此重启后握手仍可继续。

  • List: devices_list 会返回未撤销的设备,并叠加一个实时的 peer_online 标志,该标志来源于 tunnel:peer-status (在线状态从不持久化保存)。

  • Revoke: devices_revoke 会软删除该设备,清除该通道所有内存中的状态和隧道状态,并发布一个 DeviceRevoked 事件。当前的撤销仅发生在本地:后端通道会等待其配对令牌 TTL 到期后自然失效(后端撤销接口会在后续补上)。


另请参阅

  • 隐私与安全:OpenHuman 如何处理你的数据和密钥。

  • 语音:按住说话和听写,是手机伴侣的核心使用场景。

最后更新于