IoT 设备身份建立:从 PIN/PAKE 到 AuthCode 会话
IoT 设备身份建立:从 PIN/PAKE 到 AuthCode 会话
摘要
IoT 设备首次接入和日常控制面对的是两类不同问题:首次接入时,设备可能只有 PIN,没有长期身份;日常控制时,系统则需要低开销地验证控制端并复用安全会话。
本文说明 PIN/SPEKE、CloudSetup、AuthCode 与本地控制 Session 的关系:它们不是替代方案,而是身份建立链路中的不同阶段。
1. 网络、身份和会话是三件不同的事
IoT 接入流程中有三个容易混淆的概念:
- 网络连接:设备是否拥有 IP,双方是否可达;
- 设备身份:控制端正在访问的是否是预期设备;
- 安全会话:双方是否拥有一致的临时密钥和消息序列状态。

设备连上 Wi-Fi 只完成第一层。没有身份时,控制端不能安全地下发长期凭据;没有 Session 时,也不能高效执行后续控制。
2. 首次接入的威胁模型
首次接入通常面临以下风险:
- PIN 空间有限,不能把 PIN 本身当作长期密钥;
- 本项目基于 UDP 的本地 CoAP 通信可能被监听、重放或伪造;
- 控制端需要确认设备确实持有相同 PIN;
- 设备身份尚未建立,无法直接执行 AuthCode 校验;
- 首次配置成功后,不应继续依赖固定 PIN 执行所有业务控制。
PIN/SPEKE 的目标是在设备没有长期身份时,利用双方已知 PIN 建立临时安全通道,而不是永久替代 AuthCode。
3. 身份材料分别解决什么问题
| 字段 | 作用 |
|---|---|
| devId | 设备的逻辑身份 |
| authCodeId | 标识本次使用哪一份认证材料 |
| authCode | 参与认证或会话密钥派生的安全材料 |
| uidHash | CloudSetup 中的用户或授权关联字段 |
| PUUID | 控制端的应用层稳定标识,不是密码学凭据 |
| sessId | 标识一次已经协商完成的控制 Session |
authCodeId 不是密钥,更像认证材料的索引;双方仍需持有匹配的 authCode 等安全输入。sessId 也不是设备身份,它必须与会话密钥、序列号和有效期一起使用。当前 AuthCode 建链中,authCode 是认证与派生输入,uidHash 则是 CloudSetup 的关联字段,不应混为同一类密钥材料。
4. PIN/SPEKE:建立临时安全通道
设备尚未拥有 devId/authCodeId 时,控制端可以使用 PIN 发起本组件中称为 SPEKE 的 PAKE 类协商。

SPEKE 成功表示双方建立了临时安全通道,但设备仍处于“未身份化”状态。此时可以安全下发身份信息,却不应把该通道误认为长期本地控制 Session。安全性还依赖双方随机数、消息校验和密钥确认的正确实现;PAKE 不消除弱 PIN、在线猜测、端点泄露等风险。
5. CloudSetup:改变设备身份状态
CloudSetup 的核心作用是把设备从“未身份化”迁移到“已身份化”。

CloudSetup 请求通常包含 devId、authCodeId、authCode 和 uidHash,应通过已建立的安全通道传输。
CloudSetup 成功不表示 5686 本地控制 Session 已自动创建。身份状态改变后,控制端应重新发现设备并进入 AuthCode 连接流程;5686 是本项目的本地控制端口。
6. AuthCode:验证长期本地控制身份
设备已发布 devId 和 authCodeId 后,控制端可以使用匹配认证材料请求创建本地控制 Session。

AuthCode 路径适合长期控制,因为它不需要每条命令重新执行 SPEKE,并且可以为每个 Session 维护独立序列号、有效期和加密状态。
7. 两条身份建立路径与会话边界
设备经 BLE 同时获得网络和身份配置时,入网后可直接走 AuthCode;若 BLE 只完成配网,则通过 PIN/SPEKE 与 CloudSetup 补充身份,再重新发现并创建 AuthCode Session。两种路径不同,但最终都回到“身份已写入、会话已创建”的同一状态。
身份材料用于证明“双方是谁”,会话密钥用于保护“本次通信”。正确生命周期为:

会话密钥不应写入日志,也不应在设备找不到 Session 时绕过校验继续执行命令。设备重启后内存会话丢失属于正常情况,控制端应重新创建 Session。
8. 密钥派生与数据加密
密钥派生函数负责把口令、认证材料、随机数等输入转换成固定长度密钥。它与加密算法解决的问题不同:
| 能力 | 解决的问题 |
|---|---|
| PBKDF2 | 增加低熵口令推导成本,生成固定长度材料 |
| HKDF | 从已有高熵秘密派生不同用途的子密钥 |
| AES-GCM | 在认证标签被验证时,为业务数据提供机密性和完整性保护 |
当前工程中,本地控制 AuthCode 会话和 SPEKE 协议版本可能走不同的派生组合。协议双方必须在算法、摘要类型、salt、info、迭代次数和输出长度上完全一致。任何一个字段不同,最终都表现为“请求到达但解密失败”。
AES-GCM 要求同一密钥下 IV/Nonce 唯一;若实现以 sequence 构造 IV,sequence 必须单调且不能回退。sequence 是协议字段,并不天然等同于 IV,最终应以具体 IV 构造实现为准。
身份材料应来自可信服务、生产系统或安全绑定流程。离线联调可使用预置测试材料,但不得复用于量产设备,也不应写入公开日志。
9. 安全失败时如何处理
| 失败位置 | 正确行为 |
|---|---|
| SPEKE 参数或证明无效 | 终止临时协商,不创建 Session |
| CloudSetup 解密失败 | 不修改设备身份 |
| 身份字段缺失 | 返回明确错误,保持原状态 |
| 身份持久化失败 | 不发布新的 authCodeId |
| AuthCode 不匹配 | 拒绝创建本地控制 Session |
| Session 响应校验失败 | 不保存、不初始化、不发送控制命令 |
| 业务命令认证失败 | 失效当前 Session,要求重新连接 |
失败处理的核心是避免“半成功状态”。系统宁可重新协商,也不应保留字段不完整或双方理解不同的身份记录。
10. 验证思路
验证身份链路时,应分别观察:
- 未身份化设备的发现响应是否缺少 authCodeId;
- SPEKE 是否完成双向协商;
- CloudSetup 是否返回成功且设备保存身份;
- 重新发现后是否发布 devId/authCodeId;
- AuthCode Session 是否成功创建;
- 控制命令是否使用新 Session,以及认证标签与 sequence 是否校验成功。
测试程序可以把 SPEKE 和 CloudSetup 拆开验证,也可以使用一键接口连续执行,但日志中必须能区分两个阶段。
至少覆盖正确/错误 PIN、CloudSetup 字段完整性、重新发现后的身份发布、AuthCode 建会话,以及设备重启后的旧会话失效与重建。
11. 总结
PIN/SPEKE 与 AuthCode 并不是重复设计。PIN/SPEKE 解决无长期身份设备的首次安全接入,CloudSetup 完成身份状态迁移,AuthCode 验证长期身份,本地控制 Session 则保护后续高频业务通信。
理解这四层关系后,就能准确区分“网络已连接”“临时安全通道已建立”“身份已写入”和“本地控制 Session 可用”四种不同状态。
参考
更多推荐
所有评论(0)