- Rust 53.3%
- TypeScript 19.3%
- Kotlin 15.7%
- JavaScript 6.5%
- Python 2.1%
- Other 3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Publish docs / publish (push) Successful in 2m41s
|
||
| .forgejo/workflows | ||
| apps | ||
| assets | ||
| crates | ||
| docs | ||
| examples/host-integration | ||
| protocol | ||
| scripts/ci | ||
| shared/design | ||
| tools | ||
| .envrc | ||
| .gitattributes | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CONTEXT.md | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| LICENSE | ||
| NOTICE | ||
| PRD.md | ||
| README.md | ||
| rust-toolchain.toml | ||
iroh-pairing
iroh-pairing 是一套面向 iroh 应用的开源双扫码设备配对与身份验证工具包:两台对等端点各自生成一次性二维码邀请,由手机介绍者(Web 或 Android)扫码撮合会合后,两端在端到端加密配对通道上独立完成完整 Matrix SAS 本地人工确认与受控业务授权。
- 文档站点与官方 Web 扫码器 / PWA:https://iroh-pairing.gjz010.page · https://iroh-pairing.gjz010.page/pair/(CLI
--connector-url规范值固定为无尾斜杠的https://iroh-pairing.gjz010.page/pair) - Android 预发布 APK(
v0.1.0-rc.1):iroh-pairing-v0.1.0-rc.1-arm64.apk(Release 详情 · 安装说明) - 源码仓库:https://git.gjz010.com/gjz010/iroh-pairing
- 许可证:Apache-2.0(由
gjz010独立维护,非 n0 computer 官方项目)
核心能力
- 轻量附着既有宿主
Endpoint:iroh-pairing直接复用宿主已有的iroh::Endpoint(支持Router注册或手写accept分发),不创建第二个Endpoint,取消或超时绝不关闭宿主连接。 - 介绍者与本地验证严格隔离:手机端(
connector-web/connector-android)仅执行邀请兼容性检查、Introduce撮合与Observe状态观察,不持有 SAS 秘密、不接触业务载荷、不提供代确认按钮;身份验证由两个端点各自在本地核对完整 7 个 Matrix SAS 表情(及 3 个十进制数)后确认。 - 连接级门禁与业务载荷回执:验证完成后可双向交换最多 64 KiB 的有类型引导载荷(带显式协议回执);宿主在核验
VerifiedPeer的业务profile与scope后,可通过可选PairingGate(EndpointHooks)授予或撤销指定业务 ALPN 的连接访问权限。
系统架构与工作流
- 生成邀请:端点 A 与端点 B 各自创建一次性、限时的 CBOR 邀请并展示二维码(含公开
EndpointId、地址提示、一次性介绍 token 与业务ApplicationContext)。 - 手机单键连续扫码与自动介绍:打开手机介绍器,主屏同屏展示端点 A / 端点 B 等权卡片;点击底部主**“扫码 / Scan”**按钮依次读取两份邀请(扫入后卡片外露自报应用名与
profile_id,并明确标注“自报名称,尚未验证”)。第二份有效且兼容的邀请录入后,手机自动向两端发送Introduce递交对方公开描述。 - 双端独立 SAS 确认与交换:两端收到介绍回执(handoff)后建立端到端加密的
/iroh-pairing/1配对连接(支持 UDP 直连或经 relay 转发)并运行 Matrix SAS;操作者在两个端点本机核对 7 个表情一致并分别输入确认后,完成双向 MAC 校验、载荷回执交换及受保护业务 ALPN 放行。此时手机退出观察或关闭页面不影响两端继续配对。
图为 connector-web 浏览器端界面(非 Android 真机截图):卡片外露自报服务摘要,底部提供单一主“扫码”入口。
快速体验:双端点已认证聊天室(pair-demo chat)
pair-demo chat 在同一宿主 Endpoint 与 Router 上同时挂载配对协议与 iroh-gossip,演示两个端点完成 SAS 验证后建立受 PairingGate 保护的双端聊天室(仅用于双端点配对演示,非多人聊天室平台)。工具链与 devenv 环境准备详见 docs/build-environment.md。
1. 构建并启动两个终端端点
cargo build -p pair-demo
# 终端 1:启动端点 A(默认使用 iroh 官方 N0 preset:UDP 直连 + N0 relay + DNS 发现)
./target/debug/pair-demo chat --name A
# 终端 2:启动端点 B
./target/debug/pair-demo chat --name B
2. 使用手机介绍器扫码撮合
任选以下一种介绍器依次扫描终端 A、B 的二维码(或在扫码弹层内选择“改用粘贴邀请”粘贴终端输出的 Invitation (paste/scan): ... 文本):
- Android 原生应用(
connector-android):构建并安装 APK(包名为com.gjz010.irohpairing;若设备曾安装旧包名computer.iroh.pairing.android,新包不会原地覆盖,二者可并存,确认迁移后可自行卸载旧应用):cd apps/connector-android printf 'sdk.dir=%s\n' "$ANDROID_HOME" > local.properties ./gradlew --no-daemon assembleDebug adb install -r app/build/outputs/apk/debug/app-debug.apk - 静态 Web 应用 / PWA(
connector-web):可使用 https://iroh-pairing.gjz010.page/pair/(支持作为 PWA 安装到主屏幕,仅缓存静态界面与 WASM),或在已加载docs/build-environment.md工具链的本地环境中安装依赖并构建预览(浏览器端运行在browser_relay模式,即使离线可打开 PWA 界面或处于同一 Wi-Fi,配对仍须经过默认官方 N0 relay 或自定义可达 relay):cd apps/connector-web PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 node .yarn/releases/yarn-4.10.3.cjs install --immutable node .yarn/releases/yarn-4.10.3.cjs build node .yarn/releases/yarn-4.10.3.cjs vite preview --host 127.0.0.1 --port 4173
3. 本地确认 SAS 并开始收发消息
- 第二份邀请录入后,手机自动完成介绍并提示在两个端点上确认。
- 核对终端 A 与终端 B 打印的 7 个 SAS 表情及 3 个十进制数完全一致,在两个终端分别输入
yes回车。 - 终端显示
Chat joined with verified peer ...后即可直接输入文字回车双向聊天;输入/quit或按Ctrl-C干净退出。
可选:纯局域网离线模式(
--lan-only) 若需在完全不访问任何 relay 或公网发现的局域网内运行,可在两端执行./target/debug/pair-demo chat --name A --lan-only与--name B --lan-only,并在connector-android页头右上齿轮“设置”中将网络模式切换为**“仅局域网”,关闭弹窗后点击页头右上角刷新图标**开始新一组配对。(connector-web受限于浏览器网络模型,不支持--lan-only邀请。)
接入现有 iroh 应用
将 iroh-pairing 附加到宿主已有的 Endpoint 与 Router(完整可运行工程见 examples/host-integration/ 与 docs/library-integration.md):
use iroh::endpoint::presets;
use iroh::protocol::Router;
use iroh::Endpoint;
use iroh_pairing::{
InviteRequest, NetworkMode, Pairing, PairingConfig, SessionEvent, PAIRING_ALPN,
};
let endpoint = Endpoint::builder(presets::N0).bind().await?;
// 附着到宿主已有的 Endpoint,并与业务 handler 一起注册到同一个 Router
let pairing = Pairing::attach(endpoint.clone(), PairingConfig::default());
let _router = Router::builder(endpoint.clone())
.accept(PAIRING_ALPN, pairing.handler())
.accept(BUSINESS_ALPN, business_handler)
.spawn();
// 创建邀请并在本地处理 SAS 确认
let session = pairing
.create_invite(InviteRequest::new("my-app", "node-a", app_ctx, NetworkMode::Internet))
.await?;
let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
if let SessionEvent::SasReady { display } = event {
// 在本机 UI 展示 display.emojis(7 项)与 display.decimals(3 项),由本地操作者确认:
session.confirm(user_confirmed_match)?;
}
}
如需连接级 ALPN 门禁(AuthorizationState / PairingGate),请在 Endpoint::builder(...).hooks(state.gate()) 阶段安装。注意 PairingGate 只执行 (EndpointId, ALPN) 连接级拦截,不会自动替宿主校验业务 profile 或资源 scope:宿主收到 SessionEvent::Verified { peer } 后,必须先校验 peer.application() 与 peer.scope() 符合预期,再调用 state.grant(...) 授予对应业务 ALPN 权限(详见 docs/authorization.md)。
仓库结构与文档索引
| 组件 | 路径 | 说明 |
|---|---|---|
iroh-pairing |
crates/iroh-pairing/(wire:crates/pairing-wire/) |
设备端配对库:复用宿主 Endpoint、Matrix SAS、载荷回执、可选 PairingGate 与脱敏诊断 |
pair-demo |
crates/pair-demo/ |
命令行演示工具:invite、chat(双端 iroh-gossip 聊天室)、peers、serve、ping |
connector-core |
crates/connector-core/(FFI:crates/connector-android-bindings/) |
手机端共享介绍核心,提供 wasm-bindgen 与 UniFFI Kotlin 绑定 |
connector-web |
apps/connector-web/ |
SolidJS + TypeScript + Vite 静态手机 Web 扫码介绍应用与 PWA |
connector-android |
apps/connector-android/ |
Kotlin + Jetpack Compose + CameraX 原生 Android 扫码介绍应用(com.gjz010.irohpairing) |
- 用户与集成文档站:
apps/docs/(https://iroh-pairing.gjz010.page) - 根仓库技术与协议资料:库接入指南 · 连接级授权 Gate · CLI 合同 · Gossip 聊天室示例 · Web 端说明 · Android 端说明 · 脱敏诊断 · 协议规范(
protocol/) · 本地自动化验收记录
本地自动化测试覆盖了协议向量、多进程 CLI、WASM 浏览器与 JVM 绑定路径;跨公网环境、自定义 HTTPS 部署及物理手机真机相机路径请在目标环境中自行验证。
许可证与归属
本项目基于 Apache License 2.0 开源,由 gjz010 维护。iroh-pairing 是独立社区项目,与 iroh 项目及其官方团队、n0 computer 不存在隶属或其他官方关联,也未获其赞助、认可或背书。相关名称与商标归各自权利人所有。项目品牌 Logo(assets/icon.svg 及其派生品牌图标)由 gjz010 创作,采用 CC BY 4.0 许可发布(详见 assets/LICENSE.md 与 NOTICE)。上游依赖(iroh、iroh-gossip、vodozemac 等)及共享语义图标(Tabler Icons MIT License,详见 shared/design/icons/SOURCE.md)各自保留原项目名称与许可证。