组密钥管理 Cluster(GroupKeyManagement)

Cluster ID: 0x003F  |  所在 Endpoint: Endpoint 0(根端点)

GroupKeyManagement 负责管理 Matter 网络中用于组播(multicast)通信的加密密钥。 当你需要向一组设备同时发送命令(比如「关闭客厅所有灯」)时,设备之间需要共享一套对称密钥来加密和验证组播消息。 这个 Cluster 就是用来写入、读取、删除和维护这些密钥集的。

CacheAndSync 特性(CS)

GroupKeyManagement 定义了一个 CacheAndSync(CS) Feature。 启用 CS 后,设备支持从 Distributed Compliance Ledger(DCL)缓存和同步信任的根证书, 并允许使用 CacheAndSync 安全策略。未启用 CS 的设备只能使用 TrustFirst 策略。

命令(Commands)

GroupKeyManagement Cluster 共有 4 个命令,用于管理密钥集(KeySet)的完整生命周期: 写入、读取、删除和列举。点击下方表格中的命令 ID 可跳转到对应的详细说明。

ID 名称 方向 说明
0x00 KeySetWrite Client → Server 写入或更新一个密钥集
0x01 KeySetRead Client → Server 读取指定密钥集的信息
0x03 KeySetRemove Client → Server 删除一个密钥集
0x04 KeySetReadAllIndices Client → Server 列出当前 Fabric 的所有密钥集 ID

KeySetWrite -- 写入密钥集(0x00)

写入一个完整的密钥集(GroupKeySet)到设备中。如果指定的 GroupKeySetID 已存在,则更新它。 每个密钥集包含最多三个 Epoch 密钥,用于支持密钥轮换时的平滑过渡。

参数类型说明
GroupKeySet GroupKeySetStruct 完整的密钥集结构体,包含 ID、安全策略和最多三组 Epoch 密钥
密钥安全

写入的 EpochKey 是敏感数据。设备在存储后不会回传明文密钥 —— 通过 KeySetRead 读取时,EpochKey 字段会返回 null,只能看到 EpochStartTime。

使用场景

Commissioner(如手机 App)在建立组播通信前,需要先通过 KeySetWrite 将共享密钥写入所有参与组播的设备。通常在设备配网成功后、加入组之前调用。

KeySetRead -- 读取密钥集(0x01)

读取指定 ID 的密钥集信息。返回 KeySetReadResponse, 其中包含密钥集的元数据(ID、安全策略、各 Epoch 起始时间),但不包含密钥明文。

参数类型说明
GroupKeySetID uint16 要读取的密钥集 ID

KeySetReadResponse

字段类型说明
GroupKeySet GroupKeySetStruct 密钥集信息(EpochKey 字段为 null,不返回明文)
使用场景

管理端需要确认某个密钥集是否已成功写入、查看其安全策略和 Epoch 时间窗口时调用。 常用于密钥轮换前检查当前密钥集的状态。

KeySetRemove -- 删除密钥集(0x03)

删除指定 ID 的密钥集。删除前需要确保没有 GroupKeyMap 条目仍在引用该密钥集, 否则相关组将无法正常收发加密组播消息。

参数类型说明
GroupKeySetID uint16 要删除的密钥集 ID(不能为 0,ID 0 是 IPK 密钥集,不可删除)
IPK 不可删除

GroupKeySetID 为 0 的密钥集是 Identity Protection Key(IPK), 由 Fabric 建立时自动创建。尝试删除 ID 0 会返回 INVALID_COMMAND 错误。

使用场景

密钥轮换完成后,旧密钥集不再被任何组引用时,可以通过 KeySetRemove 清理掉,释放设备存储空间。

KeySetReadAllIndices -- 列举所有密钥集(0x04)

列出当前 Fabric 下所有已存储的密钥集 ID。返回 KeySetReadAllIndicesResponse。 不需要任何参数。

KeySetReadAllIndicesResponse

字段类型说明
GroupKeySetIDs list<uint16> 当前 Fabric 拥有的所有密钥集 ID 列表
使用场景

管理端在执行密钥审计或轮换前,先调用此命令获取设备上所有密钥集的 ID, 再逐个通过 KeySetRead 查看详情,决定哪些需要更新或删除。

属性详解

GroupKeyManagement Cluster 共有 4 个应用属性。点击下方汇总表中的属性 ID 可跳转到对应的详细说明。

ID 名称 类型 可写 说明
0x0000 GroupKeyMap list<GroupKeyMapStruct> 是 组 ID 与密钥集的映射关系
0x0001 GroupTable list<GroupTableStruct> 否 设备上所有组的信息表
0x0002 MaxGroupsPerFabric uint16 否 每个 Fabric 最多支持的组数量
0x0003 MaxGroupKeysPerFabric uint16 否 每个 Fabric 最多支持的密钥集数量

GroupKeyMap -- 组密钥映射(0x0000)

这是本 Cluster 最核心的属性。它定义了「哪个组使用哪个密钥集」的映射关系。 每个条目将一个 GroupId 关联到一个 GroupKeySetID,设备根据这个映射来选择加解密组播消息所用的密钥。

可写属性 —— 管理端可以直接写入来建立或修改映射。 一个密钥集可以被多个组共享,也可以为每个组分配独立的密钥集。

GroupKeyMapStruct 结构

字段类型说明
GroupId group-id 组 ID(对应 Groups Cluster 中注册的组)
GroupKeySetID uint16 关联的密钥集 ID(必须是已通过 KeySetWrite 写入的)
FabricIndex fabric-idx 所属 Fabric 索引(自动填充,Fabric 隔离)

GroupTable -- 组信息表(0x0001)

只读属性,展示设备上所有已注册组的详细信息。 这个表由设备根据 Groups Cluster 的操作和 GroupKeyMap 自动维护,不能直接写入。

GroupTableStruct 结构

字段类型说明
GroupId group-id 组 ID
Endpoints list<endpoint-no> 该组包含的 Endpoint 列表
GroupName string 组名称(最长 16 字节,可选)
FabricIndex fabric-idx 所属 Fabric 索引

MaxGroupsPerFabric -- 最大组数(0x0002)

只读属性,标识每个 Fabric 最多可以注册多少个组。 这是设备的硬件/固件限制,管理端在规划组播拓扑时需要参考这个值。

MaxGroupKeysPerFabric -- 最大密钥集数(0x0003)

只读属性,标识每个 Fabric 最多可以存储多少个密钥集。 包括 IPK(ID = 0)在内。如果值为 3,则除了 IPK 外还能存 2 个自定义密钥集。

容量规划

在写入密钥集或添加组映射前,先读取 MaxGroupsPerFabric 和 MaxGroupKeysPerFabric 确认设备还有空间。 超出限制的写入操作会返回 RESOURCE_EXHAUSTED 错误。

数据结构

GroupKeySetStruct(密钥集结构体)

描述一个完整的组播密钥集。包含密钥集 ID、安全策略、以及最多三组 Epoch 密钥和对应的起始时间。 三个 Epoch 插槽用于支持密钥轮换 —— 设备可以同时持有旧密钥和新密钥,实现无缝切换。

字段类型说明
GroupKeySetID uint16 密钥集唯一标识。0 为 IPK(Identity Protection Key),由 Fabric 自动管理
GroupKeySecurityPolicy GroupKeySecurityPolicyEnum 安全策略 —— TrustFirst 或 CacheAndSync
EpochKey0 octstr (16 bytes) / null 第一个 Epoch 密钥(128 位 AES 密钥)。读取时返回 null
EpochStartTime0 epoch-us / null EpochKey0 的生效时间(微秒级 UTC 时间戳)
EpochKey1 octstr (16 bytes) / null 第二个 Epoch 密钥。用于密钥轮换过渡期
EpochStartTime1 epoch-us / null EpochKey1 的生效时间
EpochKey2 octstr (16 bytes) / null 第三个 Epoch 密钥。完成轮换后的最终密钥
EpochStartTime2 epoch-us / null EpochKey2 的生效时间
Epoch 密钥轮换机制

三个 Epoch 插槽按时间顺序排列:EpochStartTime0 < EpochStartTime1 < EpochStartTime2。 设备在当前时间到达对应的 EpochStartTime 后自动切换到新密钥。 在切换窗口期内,设备能同时用旧密钥解密收到的消息、用新密钥加密发出的消息, 保证组内设备逐步更新密钥时不会中断通信。

枚举类型

GroupKeySecurityPolicyEnum(安全策略)

定义密钥集使用的安全验证策略。决定设备如何验证组播消息的来源可信度。

0
TrustFirst 信任优先 —— 首次收到的组播密钥即被信任。适用于大多数场景,是默认策略
1
CacheAndSync 缓存与同步 —— 需要从 DCL 验证证书链后才信任。安全性更高,需要设备支持 CS 特性
CacheAndSync 前提

只有设备的 FeatureMap 中启用了 CS 位后, 才能在 KeySetWrite 中使用 CacheAndSync 策略。 向不支持 CS 的设备写入 CacheAndSync 密钥集会返回 INVALID_COMMAND。

Feature 位图

GroupKeyManagement Cluster 通过 FeatureMap(0xFFFC)声明设备支持的高级能力:

Bit 0
CS(CacheAndSync) 缓存与同步 —— 支持从 DCL 同步信任根证书,允许使用 CacheAndSync 安全策略

示例数据

一个已配置两个组的设备上,GroupKeyManagement Cluster 的属性读取结果:

{
  // --- GroupKeyMap(密钥映射表)---
  "0x0000": [
    {
      "GroupId": 1,
      "GroupKeySetID": 1,
      "FabricIndex": 1
    },
    {
      "GroupId": 2,
      "GroupKeySetID": 1,
      "FabricIndex": 1
    }
  ],

  // --- GroupTable(组信息表,只读)---
  "0x0001": [
    {
      "GroupId": 1,
      "Endpoints": [1, 2],
      "GroupName": "客厅灯组",
      "FabricIndex": 1
    },
    {
      "GroupId": 2,
      "Endpoints": [3],
      "GroupName": "卧室灯组",
      "FabricIndex": 1
    }
  ],

  // --- 容量限制 ---
  "0x0002": 4,               // MaxGroupsPerFabric = 4
  "0x0003": 3                // MaxGroupKeysPerFabric = 3
}
开发提示

GroupKeyMap 是唯一可写的属性 —— 通过写入它来绑定组和密钥集。 GroupTable 是只读的,由设备自动根据 Groups Cluster 和 GroupKeyMap 计算生成。 密钥集本身通过 KeySetWrite / KeySetRead 命令管理,不通过属性读写。

常见场景

场景 1:为一组设备建立组播密钥

当你需要让多个设备加入同一个组并支持组播通信时:

  1. 先读取目标设备的 MaxGroupKeysPerFabric (0x0003),确认还有密钥集配额
  2. 通过 KeySetWrite (0x00) 向每个目标设备写入相同的密钥集(相同的 GroupKeySetID 和 EpochKey)
  3. 在每个设备上写入 GroupKeyMap (0x0000) 属性,将 GroupId 映射到刚写入的 GroupKeySetID
  4. 通过 Groups Cluster 的 AddGroup 命令将设备加入对应的组
  5. 读取 GroupTable (0x0001) 确认组信息和 Endpoint 映射正确
  6. 现在可以向该组发送组播命令了,所有成员设备都能用共享密钥解密和执行

场景 2:密钥轮换(Key Rotation)

定期更换组播密钥是安全最佳实践。Matter 的三 Epoch 机制让轮换可以无缝进行:

  1. 通过 KeySetReadAllIndices (0x04) 列出当前所有密钥集 ID
  2. 通过 KeySetRead (0x01) 读取目标密钥集,检查当前的 Epoch 时间窗口
  3. 生成新的 128 位 AES 密钥作为下一个 Epoch 密钥
  4. 通过 KeySetWrite (0x00) 更新密钥集 —— 保留当前活跃的 EpochKey,将新密钥写入下一个 Epoch 插槽,设置未来的 EpochStartTime
  5. 依次向组内每个设备写入相同的更新后密钥集
  6. 等待所有设备都更新完毕后,新 EpochStartTime 到达时自动切换到新密钥
  7. 确认所有设备已切换后,可以移除不再使用的旧 Epoch 密钥(通过下一次 KeySetWrite 覆盖)
轮换要点

密钥轮换的关键是 先写入所有设备,再让新密钥生效。 如果部分设备还持有旧密钥而其他设备已切换到新密钥,这些设备之间的组播通信将中断。 因此建议将 EpochStartTime 设置到足够远的未来,确保所有设备都有时间完成更新。