特性

GATT 服务的服务和特性

快速配对提供程序应具有以下 GATT 服务。

服务 UUID
快速配对服务 0xFE2C

此服务应具有以下特征。

自定义特征

快速配对服务特征 已加密 权限 UUID
模型 ID 读取 FE2C1233-8366-4814-8EB0-01DE32100BEA
基于密钥的配对 撰写和通知 FE2C1234-8366-4814-8EB0-01DE32100BEA
通行密钥 撰写和通知 FE2C1235-8366-4814-8EB0-01DE32100BEA
帐号密钥 书写 FE2C1236-8366-4814-8EB0-01DE32100BEA

标准特征

名称 已加密 权限 UUID
固件修订版本 读取 0x2A26

特征:模型 ID

当设备在可检测模式下投放广告时,此功能可让 Seek 根据需要读取模型 ID。它应始终返回以下数据:

八位字节 数据类型 说明
0 - 2 条 uint24 模型 ID 不尽相同

特征:基于密钥的配对

此特性控制基于密钥的配对过程。在此过程中,需要验证 Seek 和 Provider 是否都拥有预共享密钥,从而建立一定程度的信任。密钥在每种情况下都不同:

  • 案例 1:预共享密钥基于反欺骗公钥/私钥对以及 Seeker 自己的公钥/私钥对,每次尝试配对时,此对都会更改。

    • 提供商处于配对模式。
    • 验证器验证提供程序是否拥有防仿冒私钥。

    请注意,在配对模式下,提供程序当然还可以按常规方式配对,例如,与不支持快速配对的基于密钥的配对的设备配对。

  • 案例 2:预共享密钥是帐号密钥之一。

    • 提供程序通常不处于配对模式。(但这不是强制要求 - 即使在配对模式下,提供方也应支持使用帐号密钥。)
    • 还原方和提供方都会验证另一方是否拥有帐号密钥。

由于这两种情况极为相似,但使用哪个预共享密钥的情况除外,因此它们会在过程中合并。

数据格式

如需了解每种格式的使用方式,请参阅流程

八位字节 数据类型 说明 是否必须填写?
0 - 15 uint128 加密请求 不尽相同 强制
16-79 周岁 公钥 不尽相同 选填

表 1.1:搜索者写入特征的加密请求。

八位字节 数据类型 说明 是否必须填写?
0 uint8 邮件类型 0x00 = 基于密钥的配对请求 强制
1 uint8 标志
  • 位 0 (MSB):已废弃并由 Seeker 忽略。
  • 位 1:1,如果“探究者”要求提供方发起绑定,并且此请求中包含“探寻者”的 BR/EDR 地址。否则为 0。
  • 位 2:1(如果 Seek 要求提供方通知现有名称)。否则为 0。
  • 位 3:如果为追溯性地写入帐号密钥,则为位 1。否则为 0。
  • 位 4 - 7 保留以供将来使用,应忽略。
不尽相同 强制
2 - 7 条 uint48 请执行以下任一操作:
  • 提供商的当前 BLE 地址
  • 提供方的公开地址
不尽相同 强制
8 - 13 岁 uint48 寻求者的 BR/EDR 地址 不尽相同 仅在设置了位 1 或 3 时存在
n - 15 条 随机值 (salt) 不尽相同 强制

表 1.2.1:原始请求(类型 0x00)。使用表 1.1 中的加密请求进行解密。

八位字节 数据类型 说明 是否必须填写?
0 uint8 邮件类型 0x10 = 操作请求 强制
1 uint8 标志
  • 位 0 (MSB):如果是设备操作,则为 1,否则为 0。
  • 位 1:1,如果后跟更多数据特征,则为 0,否则为 0。
  • 位 2-7 保留以供将来使用,应将其忽略。
不尽相同 强制
2 - 7 条 uint48 请执行以下任一操作:
  • 提供商的当前 BLE 地址
  • 提供方的公开地址
不尽相同 强制
8 uint8 消息组 不尽相同 如果设置了 Flags 位 0,则必需
9 uint8 邮件内容代码 不尽相同 如果设置了 Flags 位 0,则必需
10 uint8 取决于标志:
  • 已设置位 0:额外的数据长度,小于 6
  • 已设置位 1:数据 ID
不尽相同 如果设置了标记位 0 或 1,则必需
11 - n 附加数据 不尽相同 选填
n - 15 条 随机值 (salt) 不尽相同 强制

表 1.2.2:原始请求(类型 0x10)。使用表 1.1 中的加密请求进行解密。

八位字节 数据类型 说明
0 uint8 邮件类型 0x01 = 基于密钥的配对响应
1 - 6 条 uint48 提供方的公开 (BR/EDR) 地址 不尽相同
7 - 15 条 随机值 (salt) 不尽相同

表 1.3:原始响应。已加密以生成加密响应表 1.4

八位字节 数据类型 说明
0 -15 uint128 加密响应 不尽相同

表 1.4:提供方通过通知发送给 Seek 的加密响应。

特征:密钥

该特性在基于密钥的配对过程中使用。

八位字节 数据类型 说明
0 - 15 uint128 加密的通行密钥块 不尽相同

表 2.1:加密的通行密钥块。有关使用方法,请参阅基于密钥的配对过程。

八位字节 数据类型 说明
0 uint8 邮件类型 以下各项中的一项:
  • 0x02 = 搜寻者的通行密钥
  • 0x03 = 提供商的通行密钥
1 - 3 次 unit32 6 位数密钥 不尽相同
4 - 15 条 随机值 (salt) 不尽相同

表 2.2:原始密钥块。表 2.1 的解密版本。

特征:帐号密钥

配对后,快速配对查找工具会将帐号密钥写入快速配对提供程序。

八位字节 数据类型 说明
0 - 15 uint128 帐号密钥(已加密) 不尽相同

收到写入请求后,快速配对提供程序应执行以下操作:

  1. 使用过程中第 4 步生成的共享密钥对帐号密钥进行解密。
    1. 在解密之前,验证是否使用了共享密钥来解密第 12 步中的通行密钥请求。如果使用此 Secret 时未经过此步骤,请忽略这项写入操作并退出。
    2. 此时,共享密钥(在本过程中为 K)将不会再次用于此配对。凡是使用此密钥加密但未重启过程的请求,都应被拒绝。
  2. 验证解密后的值是否以 0x04 开头。如果没有,请忽略此写入并退出。
  3. 检查持久化的帐号密钥列表是否有足够的空间来存储新值。
  4. 如果没有,请从列表中删除最不常用的值。
  5. 将新值添加到列表中。

列表中的帐号密钥用于基于密钥的配对

特征:固件修订版本

此特性允许 Seek 根据需要读取提供程序的固件修订版本。它应始终返回以下数据:

八位字节 数据类型 说明
0 - var utf8s 固件修订版本代码 不尽相同

即使提供程序上有多个固件(例如,左侧耳机、右侧耳机和充电盒有 3 个固件),它应被封装到单个 utf8 字符串中。在特殊情况下,提供程序也可返回特定字符串:

  1. status-update:如果提供程序当前正在更新到新固件。或者,提供程序可以返回分阶段固件的版本。

  2. status-abnormal:如果提供程序处于异常状态。例如,它因为固件更新失败而出现故障。此值会导致 Seek 显示一条消息,告知用户必须立即更新。

特征:其他数据

该服务应具有以下特征。

快速配对服务特征 已加密 权限 UUID
数据 撰写和通知 FE2C1237-8366-4814-8EB0-01DE32100BEA
旧快速配对服务特征(目标将于 2021 年 1 月 1 日弃用) 已加密 权限 UUID
数据 撰写和通知 0x1237

在写入或通知此特性之前,必须通过特性 FE2C1234-8366-4814-8EB0-01DE32100BEA 握手才能获得共享密钥。AES-CTR 将用于加密流经此特性的数据,下文中对该算法进行了定义。此模式在超出单个 16 字节块的数据上更加安全。HMAC-SHA256 将用于确保数据完整性(如下文中所定义)。

八位字节 说明
0 - 7 HMAC-SHA256 的前 8 个字节。 不尽相同
8 - 15 岁 Nonce,用于 AES-CTR 加密。 不尽相同
16 - var 加密数据。 不尽相同

表 3.1:数据提供程序通过通知功能发送给探索器或写入者通过写入发送给提供程序的数据包。

八位字节 数据类型 说明
0 - var byte array 数据 视情况而定,请根据表 1.2.2 的数据 ID 对其进行解码:
  • 0x01(个性化名称):utf8s

表 3.2:原始数据。根据表 3.1 中的加密数据进行解密。

请求通知时(例如,通过表 1.2.1 中的位 2 请求个性化名称),快速配对提供商应执行以下操作:

  1. 为 Nonce 生成加密随机 8 个字节。
  2. 使用 AES-CTR 来加密数据,其中每个 16 字节的块都是使用

    encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
    

    其中

    1. AES 密钥是过程中第 4 步的共享密钥。
    2. clearBlock[i] 是从数据 [i * 16] 开始的 16 字节块。最后一个代码块可以小于 16 个字节。
  3. 执行 concat(encryptionBlock[0], EncryptBlock[1],...) 以创建加密数据。

  4. 生成 HMAC-SHA256 的方法

    sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))
    

    其中

    1. K 由 concat(shared_secret, 48-byte ZEROs) 生成,shared_secret 来自过程中的第 4 步。
    2. opad 为 64 个字节的外内边距,由值为 0x5C 的重复字节组成。
    3. ipad 内部内边距为 64 个字节,由值为 0x36 的重复字节组成。
  5. 以 HMAC-SHA256 的前 8 个字节作为数据包的前缀。

收到写入请求后,快速配对提供程序应执行以下操作:

  1. 通过检查 HMAC-SHA256 的前 8 个字节验证数据的完整性。
  2. 使用 AES-CTR 解密加密的数据,其中每个块都是使用

    clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
    

    其中

    1. 加密的块 [i]是加密后的数据块中的 16 个字节的块,从 i_16 开始。 最后一个代码块可以小于 16 个字节。
    2. 系统会通过握手生成或识别 AES 密钥,例如
      1. 命名流程 1 中,它来自 ECDH,并且不会再次用于此配对。凡是使用此密钥加密但未重启过程的请求,均应被拒绝。
      2. 命名流程 2 中,它是帐号密钥。
  3. 执行 concat(clearBlock[0], clearBlock[1],...) 可创建原始数据。