> For the complete documentation index, see [llms.txt](https://tinyhumans.gitbook.io/openhuman/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tinyhumans.gitbook.io/openhuman/zh/gong-neng/ios-companion.md).

# iOS 伴侣应用

iOS Companion 允许你用手机连接桌面上的 OpenHuman：你扫描桌面上显示的二维码，两个设备协商出一个共享密钥，从此以后手机就通过加密通道与桌面核心通信。

{% hint style="warning" %}
**实验性 / 不准备发布。** iOS 客户端仍在开发中， **不会** 作为已发布桌面产品的一部分。API、线缆格式和配对流程都可能在不另行通知的情况下变更，升级可能会强制你重新配对。请将下面的一切都视为开发者预览版。
{% endhint %}

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

***

## 它是什么

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

一旦配对完成，设备就会出现在 **设置 → 设备** 中的桌面端列表里，并且可以随时撤销。

***

## 通过二维码配对

```
桌面核心                         后端中继              iOS 应用
     |                                     |                        |
     |-- devices_create_pairing RPC        |                        |
     |-- tunnel:register ----------------->|                        |
     |<-- channel_id, expires_at ----------|                        |
     |-- 生成 X25519 密钥对               |                        |
     |-- tunnel:connect (role: core) ----->|                        |
     |                                     |                        |
     |   显示二维码:                       |                        |
     |   cid, pt, cpk, rpc?, exp           |                        |
     |.................. 扫描二维码 ......................>            |
     |                                     |   生成设备           |
     |                                     |   X25519 密钥对        |
     |                                     |<-- tunnel:connect ------|
     |                                     |    (role: client)       |
     |<------ tunnel:frame (handshake) ----|------------------------|
     |-- X25519 DH + 派生会话密钥          |                        |
     |-- 持久化 PairedDevice              |                        |
     |-- 发布 DevicePaired 事件           |                        |
     |   设备出现在 Devices 列表中        |                        |
```

二维码载荷（以 `openhuman://pair?...` 深度链接的形式传递）包含通道 id（`cid`），一个一次性配对令牌（`pt`），核心的公钥（`cpk`），一个可选的局域网 URL（`rpc`），以及一个过期时间（`exp`）。配对令牌仅可使用一次，在后端静态存储时会被哈希化，而二维码在客户端侧会在 `exp` 之后被拒绝（后端会强制执行真实的约 10 分钟 TTL）。

***

## 端到端隧道

机密性和完整性完全由两个端点承担。具体原语见 `src/openhuman/devices/crypto.rs`:

* **密钥协商：** X25519 Diffie-Hellman。双方各有一对长期静态密钥对（核心的在二维码中；设备的在扫描时生成），另外每次会话还会生成一对临时密钥对以实现前向保密。
* **会话密钥派生：** 基于 `ikm = static_dh || eph_dh`的 HKDF-SHA256，并使用 `client_eph_pub || server_eph_pub`作为盐。派生出两个 **单向的** 32 字节子密钥，并用不同的 info 标签展开（`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` 的那个。

| 策略                                | 类                            | 使用场景                            | 权衡                                                           |
| --------------------------------- | ---------------------------- | ------------------------------- | ------------------------------------------------------------ |
| **LAN 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 私钥在静态存储时会加密保存（通过操作系统钥匙串 `SecretStore`），因此即使重启，握手也能继续。

* **列表**: `devices_list` 返回未撤销的设备，并叠加一个实时的 `peer_online` 标志，该标志来源于 `tunnel:peer-status` （在线状态从不持久化）。
* **撤销**: `devices_revoke` 会软删除该设备，拆除该通道的所有内存中状态和隧道状态，并发布一个 `DeviceRevoked` 事件。如今撤销只在本地生效：后端通道会自然等待其配对令牌 TTL 到期（后端撤销端点是后续计划）。

***

## 另见

* [隐私与安全](/openhuman/zh/gong-neng/privacy-and-security.md)：OpenHuman 如何处理你的数据和密钥。
* [语音](/openhuman/zh/gong-neng/native-tools/voice.md)：按住说话和听写，这是手机伴侣的核心用例。
