蓝牙mesh Key Refresh
当一个或多个网络密钥,或者一个或多个应用程序密钥的安全性已被破坏或可能被破坏时,使用此过程(procedure )。
例如,当一个节点从网络中移除时,所有剩余的节点都需要更改其密钥,这样如果该节点在被移除后遭到破解,则被移除的节点将不知道正在使用的新密钥。 这被称为“垃圾箱攻击”。
该过程(procedure )允许将一些节点列入黑名单(即,不与一些被认为受到损害或存在安全风险的节点共享新密钥),因为新密钥的分发是基于配网器和每个节点在配网流程中建立的设备密钥。
==问题一:黑名单是怎么设置的?==
该过程(procedure )包括更改网络密钥、应用程序密钥和所有派生的凭证,在做这些操作的同时对网络运行的干扰最小。
==问题二:一次过程是对单个网络密钥或应用秘钥更新,还是包括网络密钥、应用秘钥和派生凭证整个更新完?==
节点中的每个键索引(Key Index)可以包含一个或两个键(Key)。 如果持有两个密钥,则最近添加的密钥称为新密钥,另一个密钥称为旧密钥。
密钥刷新过程(The Key Refresh procedure)管理 NetKey 及其关联的 AppKey 从旧密钥更改为新密钥的过程。 NetKey 更新过程中,其关联的 AppKey不应更改为新的值。
密钥刷新过程(The Key Refresh procedure)独立于 IV 更新过程( the IV Update procedure)。 这两个过程可以同时执行、交错执行或在不同时间执行。 IV Update过程的行为和Key Refresh过程的行为对对方均没有没有影响。
密钥刷新过程使用三个阶段将网络从仅使用旧密钥的当前状态改动到仅使用新密钥的新状态,如下图所示:
密钥刷新过程.png
==问题三、上图中各个阶段是怎么开始和结束?怎么知道要进入下一阶段,判断条件是什么?==
密钥的变化情况.png
- 第一阶段涉及向每个节点分发新密钥。 节点将继续使用旧密钥进行发送,但可以使用旧密钥和新密钥进行接收。
- 第二阶段涉及发送一个安全网络信标( Secure Network beacon),该信标表明网络中所有节点都拥有新密钥。 节点将使用新密钥进行发送,但可以使用旧密钥和新密钥进行接收。
- 第三阶段涉及发送另一个安全网络信标( Secure Network beacon),该信标表明网络中所有节点都应撤销旧密钥。 节点将仅使用新密钥进行传输和接收。
执行阶段 1(密钥分发)时,每个节点都会收到一个存储在同一密钥索引中的新密钥。对于单个节点而言,收到新密钥就代表进入阶段1,之后收到消息都会新密钥和旧密钥循环做解码。一旦所有节点都确认收到新密钥,那第二个阶段可以开始。配网器会在网络周围发送一个信号,表明现在应该使用新密钥,也就是第二阶段开始,此时发送消息使用新密钥。一旦能确定所有节点都进入了第二阶段,都在用新密钥发送消息的时候,就可以进入第三阶段。第三阶段移除旧密钥。在节点都移除旧密钥后,节点回到通常状态。
每个 NetKey的更新是独立的,与其他NetKey的更新互不影响。 一个 NetKey 的密钥刷新过程可以与节点其他 NetKey 的另一个密钥刷新过程处于不同的阶段。
==问题四:密钥刷新过程中,密钥在本地网络数据中存储的数据结构?==
为了增加 Key Refresh 过程的稳健性,节点在处理消息时,应该做异常处理:
网络密钥更新消息
ConfigNetKeyUpdate
- 当节点
Key Refresh过程尚未启动时,收到ConfigNetKeyUpdate消息,其中NetKeyIndex有效且NetKey值不同,为正确消息,应该正确处理。- 当节点处于阶段 1,收到
ConfigNetKeyUpdate消息,NetKey值相同的情况下,应该正确处理。- 当节点处于阶段 2 或阶段 3 时,收到
ConfigNetKeyUpdate消息应产生错误。应用密钥更新消息
ConfigAppKeyUpdate
- 当节点处于正常操作、阶段 2 、阶段 3 ,
ConfigAppKeyUpdate消息应产生错误。- 当节点处于阶段 1时,
AppKeyIndex有效但AppKey值不同的情况下,ConfigAppKeyUpdate消息也应产生错误。
阶段1:新密钥的分配
这一步由配网器启动。配网器应确定参与更新的节点集合,将接收新 NetKey 和绑定到它的新 AppKey 。任何未收到新密钥的节点都被列入黑名单(即,它们将在第 3 阶段有效地从网络中删除)。
配网器将新密钥发送到未列入黑名单的每个节点。 使用 Config NetKey Update 消息和 Config AppKey Update 消息分发新密钥。
收到新密钥后,节点将存储它们。 在此阶段,节点应使用旧密钥发送并使用旧密钥和新密钥进行接收。
配网器应该考虑到低功耗节点存在非常高的延迟,因此在发送新密钥时要确保有足够的时间发送到每一个节点。在接收到将 OBO 字段设置为 1 以发送到低功耗节点的密钥更新消息的分段确认时,配置客户端可以对低功耗节点的朋友节点执行轮询超时列表过程(使用 SRC 字段的值标识朋友节点 Segment Acknowledgment) 以获取 PollTimeout 计时器的当前值,并根据该值安排 NetKey 或 AppKey 更新的重试。
在第 1 阶段使用新的 NetKey 接收到密钥刷新标志设置为 0 的安全网络信标后,节点应立即转换到第 3 阶段,从而有效地跳过第 2 阶段。
当配置客户端确定所有未列入黑名单的节点都已收到新密钥时,阶段 1 完成,应过渡到阶段 2。
Config NetKey Update
Config NetKey Update 是用于更新节点上的 NetKey 的确认消息。 然后节点使用更新后的 NetKey 来验证和解密它接收到的消息,以及验证和加密它发送的消息。对 Config NetKey Update 消息的响应是 Config NetKey Status 消息。
Config NetKey Update 消息参数如下:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| NetKeyIndex | 2 | Index of the NetKey |
| NetKey | 16 | NetKey |
Config NetKey Status 消息参数如下:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Status | 1 | Status Code for the requesting message |
| NetKeyIndex | 2 | Index of the NetKey |
Config AppKey Update
Config AppKey Update 是一条确认消息,用于更新节点上 AppKey List 上的 AppKey 值。 节点使用更新的 AppKey 来验证和解密它接收到的消息,以及验证和加密它发送的消息。对 Config AppKey Update 消息的响应是 Config AppKey Status 消息。
Config AppKey Update消息参数如下:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| NetKeyIndexAndAppKeyIndex | 3 | Index of the NetKey and index of the AppKey |
| AppKey | 16 | 新的APPKey值 |
NetKeyIndexAndAppKeyIndex 字段包含两个索引,分别标识 NetKey 的全局 NetKey Index 和 AppKey 的全局 AppKey Index。
Config AppKey Status 消息参数如下:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Status | 1 | Status Code for the requesting message |
| NetKeyIndexAndAppKeyIndex | 3 | Index of the NetKey and index of the AppKey |
阶段2:切换到新Key
配置客户端应开始发送密钥刷新标志设置为 1 的安全网络信标,使用新的 NetKey 进行保护,或者通过发送 Config Key Refresh Phase Set消息来启动密钥刷新阶段转换。 转换参数设置为 0x02 到一个或多个节点。
中继节点或朋友节点,当它处于给定 NetKey 的第 2 阶段时,应为新的 NetKey 发送安全网络信标,并将密钥刷新标志设置为 1,并且它应停止为旧的 NetKey 发送安全网络信标。
在接收到密钥刷新标志设置为 1 的安全网络信标或Friend Update好友更新消息,或阶段参数设置为 0x02 的Config Key Refresh Phase Set消息时,节点应将此 NetKey 的密钥刷新阶段设置为阶段 2 。在阶段 2 中,节点应仅使用新密钥传输消息和安全网络信标,应使用旧密钥和新密钥接收消息,但仅接收使用新 NetKey 保护的安全网络信标。
配置客户端应该知道低功耗节点可能具有非常高的延迟,因此低功耗节点可能需要额外的时间来接收来自朋友节点的密钥刷新标志信息。
当配置客户端确定所有未列入黑名单的节点都处于第 2 阶段时,第 2 阶段已完成,它应过渡到第 3 阶段。
Config Key Refresh Phase Set
消息参数如下
| 参数 | 长度(字节) | 注释 |
|---|---|---|
| NetKeyIndex | 2 | NetKey Index |
| Transition | 1 | New Key Refresh Phase Transition |
Config Key Refresh Phase Set 是一条确认消息,用于设置已识别网络密钥的 Key Refresh Phase 状态。对 Config Key Refresh Phase Set 消息的响应是 Config Key Refresh Phase Status 消息。
Config Key Refresh Phase Status
消息参数如下
| 参数 | 长度(字节) | 注释 |
|---|---|---|
| Status | 1 | Status Code for the requesting message |
| NetKeyIndex | 2 | NetKey Index |
| Phase | 1 | Key Refresh Phase State |
阶段3:移除旧Key
配置客户端应开始发送密钥刷新标志(Key Refresh flag)设置为 0 的安全网络信标,使用新的 NetKey 进行加密,或者通过发送Config Key Refresh Phase Set消息并将转换参数设置为 0x03 给 一个或多个节点来启动密钥刷新阶段转换。 配置客户端应撤销旧密钥。
当设备最近被配置并且没有旧密钥时,它将不知道旧密钥,因此将无法撤销旧密钥。
当一个给定的 NetKey 处于第 3 阶段时,Relay 节点或 Friend 节点应为新的 NetKey 发送安全网络信标,并将 Key Refresh 标志设置为 0。
在接收到密钥刷新标志设置为 0 的安全网络信标 或 朋友更新消息 或 转换参数设置为 0x03 的Config Key Refresh Phase Set消息时,节点应撤销旧密钥,并为新的 NetKey 发送安全网络信标,并将密钥刷新标志设置为 0。节点将仅使用新密钥进行传输和接收。 它应忽略使用密钥刷新标志设置为 1 的新 NetKey 保护的安全网络信标和朋友更新消息。旧密钥被撤销后,密钥刷新状态将为 0。
配置客户端应该考虑到低功耗节点可能具有非常高的延迟,因此低功耗节点可能需要额外的时间来接收来自朋友节点的密钥刷新标志信息。
Key Refresh Phase参数
密钥刷新阶段状态(Key Refresh Phase state)指示和控制网络密钥列表中每个网络密钥的密钥刷新过程。
| 值 | 描述 |
|---|---|
| 0x00 | Normal operation; Key Refresh procedure is not active |
| 0x01 | First phase of Key Refresh procedure |
| 0x02 | Second phase of Key Refresh procedure |
| 0x03–0xFF | Prohibited |
下表定义可以使用此状态控制的 Key Refresh Phase 状态的所有可能转换。 所有其他转换都由密钥刷新过程在内部处理(例如,当设备接收到密钥更新时从 0x00 到 0x01 的转换)。
| Old State | Transition | New State | Description |
|---|---|---|---|
| 0x00 | 0x03 | 0x00 | Transition 3 from Key Refresh Phase 0x00 does not cause any state change. |
| 0x01 | 0x02 | 0x02 | Transition 2 from Key Refresh Phase 0x01 moves to Key Refresh Phase 0x02 |
| 0x01 | 0x03 | 0x00 | Transition 3 from Key Refresh Phase 0x01 invokes Key Refresh Phase 3 and then moves to Key Refresh Phase 0x00. |
| 0x02 | 0x02 | 0x02 | Transition 2 from Key Refresh Phase 0x02 does not cause any state change. |
| 0x02 | 0x03 | 0x00 | Transition 3 from Key Refresh Phase 0x02 invokes Key Refresh Phase 3 and then moves to Key Refresh Phase 0x00. |
实际开发中要解决的问题
1.怎么区分待更新节点和黑名单节点?NRF SDK3.0之前由黑名单列表(BlackList)区分;NRF SDK3.0以及之后的版本用节点成员变量(Excluded)来区分。
通常情况下节点属性.png
2.怎么知道密钥刷新处于哪个状态?网络密钥有一个phase属性,表示当前KEY所处的刷新状态。刷新状态KeyRefreshPhase有3种情况 normalOperation,keyDistribution,usingNewKeys。
enum KeyRefreshPhase: Int {
case normalOperation = 0
case keyDistribution = 1
case usingNewKeys = 2
}
enum KeyRefreshPhaseTransition: UInt8 {
case useNewKeys = 2
case revokeOldKeys = 3
}
3.发送密钥更新消息,需要传入想要更新的密钥。
在iOS 3.1.5的最新版本中,Key Refresh功能没有完善,需要我们自己做一定的修改。以NetworkKey更新为例,在iOS上提供两种思路供参考,一种是创建一个新的NetworkKey,在构建ConfigNetKeyUpdate消息时将新的NetworkKey传入。二种是修改ConfigNetKeyUpdate的构造方法,直接使用index和Key作为参数。
//在ConfigNetKeyUpdate.Swift文件中,新增一个方法
public init(networkKeyIndex: KeyIndex, key: Data) {
self.networkKeyIndex = networkKeyIndex
self.key = key
}
//在程序中Key Refresh的调用方式
let message = ConfigNetKeyUpdate(networkKeyIndex: 0, key: Data.random128BitKey())
4.一次过程是对单个网络密钥或应用秘钥更新,还是包括网络密钥、应用秘钥和派生凭证整个更新完?
网络密钥和应用密钥的更新是分开进行的。
- 在第一阶段,收到分配的新Key时,将新Key加入密钥信息中,同时会生成相应的派生。
- 在一个Key的更新过程中,同时会存在两个Key以及相应的派生集。
- 新Key更新成功后,旧Key以及旧Key的派生均会被移除。
5.给配网器节点发送更新和给设备节点发送更新是否有区别?
给配网器节点发送更新才会修改本地网络数据中NetKey的数据。发送给设备节点,会根据返回数据,在node的本地数据中,修改它的netKeys信息,netKeys信息是一个内部成员变量。在确定节点是否处于更新中的方法是获取节点所有的网络密钥networkKeys,而非索引数组netKeys。
处于更新第一阶段的网络密钥.png
节点中标识密钥处于更新中.png
6.第一阶段所有节点的更新流程?
逐一发送消息,在确认一个节点更新成功后,再开始下一个节点的keyUpdate操作。直到所有节点都更新成功,或者该阶段时间超时终止。同一时间,能更新的设备应该要大于1,如果有一个设备不在线,或者被黑掉了,可以往后继续执行。
7.实现的整体效果图
网络密钥刷新过程.png