> 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 伴侣应用与你的桌面 OpenHuman 配对，隧道通过二维码扫描建立。

iOS Companion 让你可以从手机访问桌面上的 OpenHuman：你扫描桌面上显示的二维码，两台设备协商出一个共享密钥，之后手机就通过加密通道与桌面核心通信。

{% hint style="warning" %}
**实验性 / 不随产品发布。** iOS 客户端仍在开发中，并且是 **不** 已发布桌面产品的一部分。API、线上的传输格式以及配对流程都可能在不另行通知的情况下变更，升级后可能会强制你重新配对。请把下面的内容都视为开发者预览。
{% endhint %}

桌面核心始终是真相来源。手机是一个轻量客户端。它不运行自己的代理程序，而是把请求转发给核心并渲染结果。

***

## 它是什么

配对由 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 ------|
     |                                     |    （角色：客户端）     |
     |<------ tunnel:frame (握手) ---------|------------------------|
     |-- X25519 DH + 派生会话密钥         |                        |
     |-- 持久化 PairedDevice              |                        |
     |-- 发布 DevicePaired 事件           |                        |
     |   设备出现在设备列表中             |                        |
```

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

***

## 端到端隧道

机密性和完整性完全由两个端点负责。确切的原语，从 `crates/openhuman-core/src/security/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` 的那个。

| 策略                                | 类                             | 使用时机                            | 权衡                                                          |
| --------------------------------- | ----------------------------- | ------------------------------- | ----------------------------------------------------------- |
| **局域网 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)：按住说话和听写，是手机伴侣的核心用例。
