Skip to content

BLE U-Key 蓝牙设备管理

Phase 47 | v1.1.0-alpha | 4 IPC 处理器 | 扩展现有驱动注册

概述

BLE U-Key 模块为 ChainlessChain 的硬件安全密钥提供蓝牙无线通信能力,扩展现有 USB U-Key 驱动。系统通过自定义 GATT 服务发送 APDU 命令,支持 USB/BLE 双通道自动切换、断线自动重连、BLE 4.2+ 安全配对加密,让用户无需 USB 线缆即可完成数字签名等安全操作。

核心特性

  • 📡 BLE GATT 通信: 通过自定义 GATT 服务发送 APDU 命令,兼容现有 USB 接口
  • 🔄 断线自动重连: 连接中断后自动重试,最多 5 次尝试,保持持久连接
  • 🔌 USB/BLE 双通道: 支持 USB 与 BLE 双传输通道,自动选择最优连接方式
  • 🔋 设备状态监控: 实时监控电量、信号强度(RSSI)、固件版本和通信统计
  • 🔒 安全配对: BLE 4.2+ Secure Connection (ECDH P-256) + AES-CCM 链路加密
  • 📱 无线签名: 摆脱 USB 线缆束缚,蓝牙无线完成数字签名操作

系统架构

┌──────────────────────────────────────────────┐
│              BLE U-Key 管理系统               │
├──────────────────────────────────────────────┤
│  前端 (Vue3)                                 │
│  ┌─────────────┐  ┌───────────────────────┐  │
│  │ BLE 设备页面 │  │ Pinia bleUkey Store  │  │
│  └──────┬──────┘  └──────────┬────────────┘  │
│         └────────┬───────────┘               │
│                  ↓ IPC                       │
├──────────────────────────────────────────────┤
│  主进程 (Electron)                           │
│  ┌──────────┐  ┌──────────┐  ┌───────────┐  │
│  │ BLE 扫描 │→│ GATT 连接 │→│ APDU 通信 │  │
│  └──────────┘  └──────────┘  └───────────┘  │
│        ↕              ↕                      │
│  ┌──────────────────────────────────┐        │
│  │  统一驱动注册 (USB + BLE 双通道) │        │
│  └──────────────────────────────────┘        │
├──────────────────────────────────────────────┤
│  硬件层: ChainlessKey Pro (BLE 4.2+)        │
└──────────────────────────────────────────────┘

BLE 通信架构

GATT 服务结构

ChainlessChain BLE 通信使用自定义 GATT 服务:

服务/特征UUID功能
Security Service0000FF01-...主安全服务
├─ Command0000FF02-...发送 APDU 命令
├─ Response0000FF03-...接收响应 (Notify)
└─ Status0000FF04-...设备状态 (Read)
Battery Service0000180F-...标准电量服务
└─ Battery Level00002A19-...电量百分比

连接流程

1. 扫描 BLE 设备 (过滤 Service UUID)
2. 连接设备 (GATT Connect)
3. 发现服务和特征
4. 订阅 Response 通知
5. 通过 Command 特征发送 APDU
6. 通过 Response 特征接收结果

核心功能

1. 设备发现

javascript
// 扫描 BLE 设备
const devices = await window.electronAPI.invoke("ukey:ble-scan", {
  duration: 10000, // 扫描 10 秒
  serviceUUIDs: ["0000FF01-0000-1000-8000-00805F9B34FB"],
});

console.log(devices);
// [
//   {
//     id: 'ble-device-001',
//     name: 'ChainlessKey Pro',
//     rssi: -45,
//     services: ['0000FF01-...'],
//     manufacturer: 'ChainlessChain',
//     batteryLevel: 85
//   }
// ]

2. 设备连接

javascript
// 连接设备
const connection = await window.electronAPI.invoke("ukey:ble-connect", {
  deviceId: "ble-device-001",
  autoReconnect: true,
});

console.log(connection);
// {
//   connected: true,
//   deviceId: 'ble-device-001',
//   mtu: 512,
//   rssi: -45,
//   services: ['0000FF01-...', '0000180F-...']
// }

// 断开连接
await window.electronAPI.invoke("ukey:ble-disconnect", {
  deviceId: "ble-device-001",
});

3. BLE APDU 通信

BLE 模式下的 APDU 通信与 USB 模式 API 兼容:

javascript
// 通过 BLE 发送 APDU 命令
const response = await window.electronAPI.invoke("ukey:ble-send-apdu", {
  deviceId: "ble-device-001",
  apdu: [
    0x00, 0xa4, 0x04, 0x00, 0x07, 0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01,
  ],
});

console.log(response);
// { sw1: 0x90, sw2: 0x00, data: [...] }

4. 自动重连

javascript
// 自动重连已在连接时启用
// 断开时会自动尝试重连

// 监听连接状态变化
// 在前端通过 store 获取实时状态
const bleStore = useBLEUkeyStore();
console.log(bleStore.connectionStatus);
// 'connected' | 'disconnected' | 'reconnecting'

驱动注册

BLE 传输已集成到统一驱动注册系统:

javascript
// 查看传输状态
const transports = await window.electronAPI.invoke("ukey:list-drivers");
// [
//   { type: 'usb', name: 'USB Transport', status: 'available' },
//   { type: 'ble', name: 'BLE Transport', status: 'available' },
//   ...
// ]

// 切换默认传输
await window.electronAPI.invoke("ukey:set-default-transport", {
  transport: "ble", // 或 'usb'
});

前端集成

Pinia Store

typescript
import { useBLEUkeyStore } from "@/stores/bleUkey";

const ble = useBLEUkeyStore();

// 扫描设备
await ble.scanDevices();

// 连接设备
await ble.connectDevice(deviceId);

// 查看连接状态
console.log(ble.connectionStatus);
console.log(ble.connectedDevice);
console.log(ble.batteryLevel);

前端页面

BLE 设备管理页面 (/ble-devices)

功能模块:

  1. 设备扫描

    • 实时扫描附近 BLE 设备
    • 信号强度排序
    • 设备过滤
  2. 设备连接

    • 一键连接/断开
    • 连接状态实时显示
    • 自动重连状态
  3. 设备信息

    • 电量显示
    • 信号强度
    • 固件版本
    • 通信统计

配置选项

json
{
  "unifiedKey": {
    "ble": {
      "enabled": true,
      "scanDuration": 10000,
      "autoReconnect": true,
      "reconnectAttempts": 5,
      "reconnectDelay": 2000,
      "serviceUUIDs": ["0000FF01-0000-1000-8000-00805F9B34FB"],
      "mtuSize": 512
    }
  }
}

使用场景

场景 1: 无线签名

javascript
// 1. 扫描并连接 BLE 设备
const devices = await window.electronAPI.invoke("ukey:ble-scan", {
  duration: 5000,
});
await window.electronAPI.invoke("ukey:ble-connect", {
  deviceId: devices[0].id,
  autoReconnect: true,
});

// 2. 通过 BLE 执行签名
const signature = await window.electronAPI.invoke("ukey:sign", {
  keyId: "signing-key-001",
  data: "transaction data",
  transport: "ble",
});

场景 2: USB/BLE 自动切换

javascript
// 系统自动检测可用传输
// USB 优先,USB 不可用时切回 BLE
const sig = await window.electronAPI.invoke("ukey:sign", {
  keyId: "signing-key-001",
  data: "message",
  transport: "auto", // 自动选择最佳传输
});

使用示例

BLE 扫描并连接签名

javascript
// 1. 扫描附近 BLE U-Key 设备
const devices = await window.electronAPI.invoke('ukey:ble-scan', {
  duration: 5000
});
console.log('发现设备:', devices.map(d => d.name));

// 2. 连接信号最强的设备
const best = devices.sort((a, b) => b.rssi - a.rssi)[0];
await window.electronAPI.invoke('ukey:ble-connect', {
  deviceId: best.id,
  autoReconnect: true
});

// 3. 通过 BLE 执行数字签名
const signature = await window.electronAPI.invoke('ukey:sign', {
  keyId: 'signing-key-001',
  data: '待签名的交易数据',
  transport: 'ble'
});
console.log('签名结果:', signature);

// 4. 查看设备电量
const status = await window.electronAPI.invoke('ukey:ble-status', {
  deviceId: best.id
});
console.log('电量:', status.batteryLevel + '%');

前端 Pinia Store 集成

typescript
import { useBLEUkeyStore } from '@/stores/bleUkey';

const ble = useBLEUkeyStore();

// 扫描设备列表
await ble.scanDevices();

// 选择并连接设备
await ble.connectDevice(ble.discoveredDevices[0].id);

// 实时监控连接状态和电量
watch(() => ble.connectionStatus, (status) => {
  if (status === 'disconnected') {
    console.warn('BLE 连接断开,正在自动重连...');
  }
});

故障排查

BLE 扫描无法发现设备

现象: 扫描超时后返回空设备列表。

排查步骤:

  1. 确认 U-Key 设备已开机且处于 BLE 广播状态(通常需长按设备按钮激活)
  2. 检查电脑蓝牙是否已开启(设置 → 蓝牙 → 开启)
  3. 确认 U-Key 电量充足(低电量时 BLE 广播可能关闭)
  4. 增大 scanDuration 参数至 15000ms,某些设备广播间隔较长

BLE 连接不稳定或频繁断开

现象: 连接建立后很快断开,自动重连反复失败。

排查步骤:

  1. 检查 U-Key 与电脑的距离,建议保持在 3 米以内
  2. 排除 WiFi 和其他蓝牙设备的 2.4GHz 频段干扰
  3. 确认 U-Key 固件版本为最新(旧固件可能有 BLE 稳定性问题)
  4. 尝试重启蓝牙适配器或重新配对设备

BLE APDU 通信超时

现象: 发送 APDU 命令后长时间无响应。

排查步骤:

  1. 检查 RSSI 信号强度,低于 -80dBm 时通信可能不稳定
  2. 确认 MTU 协商成功(默认 512 字节,部分设备可能不支持)
  3. 检查 U-Key 是否正在执行耗时操作(如密钥生成),等待完成后重试
  4. 尝试断开并重新连接设备

配置参考

完整配置项说明(对应 .chainlesschain/config.json 中的 unifiedKey.ble 节点):

json
{
  "unifiedKey": {
    "ble": {
      "enabled": true,
      "scanDuration": 10000,
      "autoReconnect": true,
      "reconnectAttempts": 5,
      "reconnectDelay": 2000,
      "rssiThreshold": -80,
      "serviceUUIDs": ["0000FF01-0000-1000-8000-00805F9B34FB"],
      "mtuSize": 512,
      "apduTimeout": 5000,
      "pairingMode": "numeric-comparison",
      "whitelist": []
    },
    "transport": {
      "default": "auto",
      "fallbackOrder": ["usb", "ble"]
    }
  }
}

配置项说明:

配置项默认值说明
enabledtrue是否启用 BLE 传输通道
scanDuration10000单次扫描持续时间(毫秒)
autoReconnecttrue连接断开后是否自动重连
reconnectAttempts5自动重连最大尝试次数
reconnectDelay2000相邻重连尝试间隔(毫秒)
rssiThreshold-80信号强度过滤阈值(dBm),低于此值的设备不显示
mtuSize512BLE MTU 协商目标大小(字节)
apduTimeout5000单条 APDU 命令最大等待时间(毫秒)
pairingModenumeric-comparison配对模式:numeric-comparison | just-works
whitelist[]已信任设备 ID 白名单,为空时允许所有已配对设备
transport.defaultauto默认传输:auto | usb | ble
transport.fallbackOrder["usb","ble"]auto 模式下的传输优先级顺序

测试覆盖率

✅ ble-transport.test.js          - BLE 连接/断开/自动重连/MTU 协商测试
✅ ble-scanner.test.js            - 设备扫描、RSSI 过滤、UUID 过滤测试
✅ apdu-handler.test.js           - APDU 命令封装、分包、响应解析测试
✅ driver-registry.test.js        - USB/BLE 双通道注册、自动切换逻辑测试
✅ stores/bleUkey.test.ts         - Pinia Store 状态管理、IPC 调用测试
✅ e2e/ukey/ble-ukey.e2e.test.ts  - 端到端设备发现→连接→签名流程测试

测试运行:

bash
# BLE 单元测试
cd desktop-app-vue && npx vitest run tests/unit/ukey/

# Store 测试
cd desktop-app-vue && npx vitest run src/renderer/stores/__tests__/bleUkey.test.ts

# 端到端测试(需要真实或模拟 BLE 设备)
cd desktop-app-vue && npx vitest run tests/e2e/ukey/

安全考虑

  1. BLE 配对: 使用 BLE 4.2+ Secure Connection (ECDH P-256)
  2. MITM 防护: 数字比较配对模式
  3. 加密通信: AES-CCM 链路层加密
  4. 距离限制: RSSI 阈值过滤远距离设备
  5. 白名单: 仅允许已配对设备重连

性能指标

指标目标实际
BLE 扫描延迟<5s~3s
BLE 连接延迟<2s~1.5s
BLE APDU 往返<200ms~150ms
自动重连时间<5s~3s

相关文档

关键文件

文件说明
desktop-app-vue/src/main/ukey/ble-transport.jsBLE 传输通道实现
desktop-app-vue/src/main/ukey/ble-scanner.jsBLE 设备扫描与发现
desktop-app-vue/src/main/ukey/driver-registry.js统一驱动注册(USB+BLE)
desktop-app-vue/src/main/ukey/apdu-handler.jsAPDU 命令处理
desktop-app-vue/src/renderer/stores/bleUkey.tsBLE U-Key Pinia Store

文档版本: 1.0.0 最后更新: 2026-02-27

基于 MIT 许可发布