No description
  • Rust 53.3%
  • TypeScript 19.3%
  • Kotlin 15.7%
  • JavaScript 6.5%
  • Python 2.1%
  • Other 3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
gjz010's OpenCode agent 44b853f16a
All checks were successful
Publish docs / publish (push) Successful in 2m41s
docs: link Android prerelease and record deployment verification
2026-10-20 16:24:23 +08:00
.forgejo/workflows fix(ci): route Android builds to high-performance runner 2026-10-20 14:30:17 +08:00
apps docs: link Android prerelease and record deployment verification 2026-10-20 16:24:23 +08:00
assets docs: license project logo under CC BY 4.0 2026-10-20 12:42:17 +08:00
crates feat: rebrand project and publish docs with a PWA scanner 2026-10-20 12:33:53 +08:00
docs docs: link Android prerelease and record deployment verification 2026-10-20 16:24:23 +08:00
examples/host-integration feat: rebrand project and publish docs with a PWA scanner 2026-10-20 12:33:53 +08:00
protocol feat(pairing): add verified SAS sessions, payload receipts and authorization gate 2026-10-19 19:45:42 +08:00
scripts/ci feat(release): build on Nix and publish signed Android releases 2026-10-20 13:28:34 +08:00
shared/design feat(release): build on Nix and publish signed Android releases 2026-10-20 13:28:34 +08:00
tools feat: rebrand project and publish docs with a PWA scanner 2026-10-20 12:33:53 +08:00
.envrc chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00
.gitattributes feat(android): deliver native scanner APK and lifecycle-safe core integration 2026-10-19 22:55:25 +08:00
.gitignore feat(release): build on Nix and publish signed Android releases 2026-10-20 13:28:34 +08:00
Cargo.lock feat(demo): demonstrate authenticated pairing with a gossip chat host 2026-10-20 11:15:29 +08:00
Cargo.toml feat: rebrand project and publish docs with a PWA scanner 2026-10-20 12:33:53 +08:00
CONTEXT.md chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00
devenv.lock chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00
devenv.nix feat(release): build on Nix and publish signed Android releases 2026-10-20 13:28:34 +08:00
devenv.yaml chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00
LICENSE feat: rebrand project and publish docs with a PWA scanner 2026-10-20 12:33:53 +08:00
NOTICE feat(release): build on Nix and publish signed Android releases 2026-10-20 13:28:34 +08:00
PRD.md chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00
README.md docs: link Android prerelease and record deployment verification 2026-10-20 16:24:23 +08:00
rust-toolchain.toml chore: establish PRD baseline and reproducible cross-platform toolchains 2026-10-19 18:40:52 +08:00

iroh-pairing

iroh-pairing

iroh-pairing 是一套面向 iroh 应用的开源双扫码设备配对与身份验证工具包:两台对等端点各自生成一次性二维码邀请,由手机介绍者(Web 或 Android)扫码撮合会合后,两端在端到端加密配对通道上独立完成完整 Matrix SAS 本地人工确认与受控业务授权。

核心能力

  • 轻量附着既有宿主 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 的连接访问权限。

系统架构与工作流

iroh-pairing 双扫码配对与 Matrix SAS 验证架构图

  1. 生成邀请:端点 A 与端点 B 各自创建一次性、限时的 CBOR 邀请并展示二维码(含公开 EndpointId、地址提示、一次性介绍 token 与业务 ApplicationContext)。
  2. 手机单键连续扫码与自动介绍:打开手机介绍器,主屏同屏展示端点 A / 端点 B 等权卡片;点击底部主**“扫码 / Scan”**按钮依次读取两份邀请(扫入后卡片外露自报应用名与 profile_id,并明确标注“自报名称,尚未验证”)。第二份有效且兼容的邀请录入后,手机自动向两端发送 Introduce 递交对方公开描述。
  3. 双端独立 SAS 确认与交换:两端收到介绍回执(handoff)后建立端到端加密的 /iroh-pairing/1 配对连接(支持 UDP 直连或经 relay 转发)并运行 Matrix SAS;操作者在两个端点本机核对 7 个表情一致并分别输入确认后,完成双向 MAC 校验、载荷回执交换及受保护业务 ALPN 放行。此时手机退出观察或关闭页面不影响两端继续配对。

connector-web 浏览器界面展示已扫描端点的自报服务摘要
图为 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 并开始收发消息

  1. 第二份邀请录入后,手机自动完成介绍并提示在两个端点上确认。
  2. 核对终端 A 与终端 B 打印的 7 个 SAS 表情及 3 个十进制数完全一致,在两个终端分别输入 yes 回车。
  3. 终端显示 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)

本地自动化测试覆盖了协议向量、多进程 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)各自保留原项目名称与许可证。