NFC 绑定¶
sim-hw 每次启动时都会生成 NFC 载荷,模拟嵌入在物理 Inklet 设备中的 NFC 标签。该载荷用于实现触碰配对的设备绑定。
载荷格式¶
| 组件 | 描述 |
|---|---|
inklet |
协议标识符 |
1 |
版本号 |
{hw_id} |
设备硬件 UUID(例如 a1b2c3d4-5678-9012-abcd-ef0123456789) |
{signature} |
HMAC-SHA256(hw_id, FACTORY_SECRET) 的前 16 个十六进制字符 |
示例:
签名生成¶
签名使用 HMAC-SHA256 计算,以出厂密钥作为密钥,硬件 UUID 作为消息。仅使用完整 HMAC 摘要的前 16 个十六进制字符(8 字节)。
import hashlib
import hmac
def generate_nfc_signature(hw_id: str, factory_secret: str) -> str:
"""Generate the NFC signature for a device hardware ID.
Args:
hw_id: Device hardware UUID string.
factory_secret: Hex-encoded factory secret (32 bytes = 64 hex chars).
Returns:
First 16 hex characters of HMAC-SHA256(hw_id, factory_secret).
"""
secret_bytes = bytes.fromhex(factory_secret)
mac = hmac.new(secret_bytes, hw_id.encode("utf-8"), hashlib.sha256)
return mac.hexdigest()[:16]
使用方式:
hw_id = "a1b2c3d4-5678-9012-abcd-ef0123456789"
secret = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
signature = generate_nfc_signature(hw_id, secret)
payload = f"inklet:1:{hw_id}:{signature}"
print(payload)
# inklet:1:a1b2c3d4-5678-9012-abcd-ef0123456789:3f7a8b2c1d9e0f4a
为什么截断到 16 个字符?
NFC 标签的存储容量有限。将 HMAC 截断到 8 字节(16 个十六进制字符)在满足 NFC 载荷大小限制的同时提供了合理的安全裕度。64 位的签名空间使得暴力攻击在设备绑定场景中不切实际。
载荷文件¶
sim-hw 每次启动时将 NFC 载荷写入 {data-dir}/nfc-payload。你可以读取此文件来模拟扫描设备的 NFC 标签。
绑定流程¶
完整的 NFC 绑定流程如下:
物理设备 sim-hw 等效操作
──────────────── ─────────────────
设备上的 NFC 标签 → 数据目录中的 nfc-payload 文件
用户将手机触碰设备 → 用户从文件中复制载荷
App 读取 NFC 载荷 → 用户在 sim-dashboard 中粘贴载荷
App 提取 hwId + sig → sim-dashboard 解析载荷
App 调用 bind/nfc API → sim-dashboard 调用 bind/nfc API
后端验证 HMAC → 后端验证 HMAC(相同)
设备绑定到用户 → 设备绑定到用户(相同)
详细步骤:
-
App 读取 NFC --- 在现实中,移动应用读取 NFC 标签。在模拟器中,你复制
nfc-payload文件的内容。 -
App 调用 API --- 应用(或 sim-dashboard)发送
POST /api/devices/bind/nfc请求,包含提取的hwId和signature: -
后端验证 --- 后端重新计算
HMAC-SHA256(hwId, FACTORY_SECRET),并将前 16 个十六进制字符与提供的签名进行比较。如果匹配,则将设备绑定到当前认证用户。 -
设备接收通知 --- 后端向设备的 MQTT 主题发布
bound命令。sim-hw 收到后显示绑定确认信息。
安全注意事项¶
出厂密钥
FACTORY_SECRET 在 sim-hw 和后端之间必须一致。在生产环境中,该密钥在出厂时烧录到设备中,并在后端的环境变量中配置。切勿在客户端代码或日志中暴露出厂密钥。
- HMAC 签名可防止未授权绑定 --- 不知道出厂密钥就无法绑定设备。
- 每个设备都有唯一的硬件 UUID,因此签名是设备专属的。
- 签名是确定性的:相同的
hw_id和FACTORY_SECRET始终生成相同的签名。这是有意为之的 --- NFC 标签的内容永远不会改变。
测试 NFC 绑定¶
使用 sim-hw 测试 NFC 绑定流程:
-
启动模拟设备:
-
读取 NFC 载荷:
-
在 sim-dashboard 中,点击"Bind Device"并粘贴 NFC 载荷字符串。
-
或者,直接调用 API:
-
设备应显示"Device bound successfully"并出现在你的仪表盘中。