特性
快速配对服务
快速配对提供程序应具有以下 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 |
---|---|
设备信息服务 | 0x180A |
快速配对查找器具有以下特征。
名称 | 已加密 | 权限 | UUID |
---|---|---|---|
固件修订版本 | 不支持 | 读取 | 0x2A26 |
特征:模型 ID
该特性允许查找器根据需要读取模型 ID,在设备以可检测模式进行通告时除外。它应始终返回以下数据:
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 2 个 | uint24 |
模型 ID | 不定 |
特征:基于密钥的配对
此特性控制基于密钥的配对程序。在此过程中,系统会通过验证探索者和提供程序是否都拥有预共享密钥来建立一定级别的信任。每种情况下的键都不相同:
情形 1:预共享密钥基于反欺骗公钥/私钥对以及搜寻者自己的公钥/私钥对,该对随每次配对尝试而改变。
- 提供商处于配对模式。
- 查找器验证提供程序是否拥有反欺骗私钥。
请注意,在配对模式下,提供程序当然也可以按常规方式进行配对,例如,与不支持快速配对密钥配对的设备配对。
-
- 提供程序通常不处于配对模式。(但这不是硬性要求 - 即使处于配对模式,提供程序也应支持使用账号密钥。)
- 探索者和提供程序会各自验证对方拥有帐号密钥。
由于这两种情况极其相似,但使用的是预共享密钥,因此将它们合并到过程中。
数据格式
请参阅过程,了解如何使用每种格式。
八位字节 | 数据类型 | 说明 | 值 | 必填? |
---|---|---|---|---|
0 - 15 | uint128 |
加密请求 | 不定 | 强制 |
16 - 79 人 | 公钥 | 不定 | 选填 |
表 1.1:加密请求,由搜索者写入特征。
八位字节 | 数据类型 | 说明 | 值 | 必填? |
---|---|---|---|---|
0 | uint8 |
邮件类型 | 0x00 = 基于密钥的配对请求 |
强制 |
1 | uint8 |
标记
|
不固定 | 强制 |
2-7 个 | uint48 |
满足以下任一条件:
|
不固定 | 强制 |
8 - 13 人 | uint48 |
追寻者的 BR/EDR 地址 | 不固定 | 仅当设置了标记位 1 或 3 时,才会显示 |
n - 15 | 随机值(盐) | 不固定 | 强制 |
表 1.2.1:原始请求(类型 0x00)。从 表 1.1 中的加密请求中解密。
八位字节 | 数据类型 | 说明 | 值 | 必填? |
---|---|---|---|---|
0 | uint8 |
邮件类型 | 0x10 = 操作请求 |
强制 |
1 | uint8 |
标记 | 不固定 | 强制 |
2-7 个 | uint48 |
满足以下任一条件:
|
不固定 | 强制 |
8 | uint8 |
消息群组 | 不固定 | 如果设置了标志位 0,则为必需 |
9 | uint8 |
邮件内容代码 | 不固定 | 如果设置了标志位 0,则为必需 |
10 | uint8 |
取决于标志:
|
不固定 | 如果设置了标记位 0 或 1,则必须提供 |
11 - nn | 附加数据 | 不固定 | 选填 | |
n - 15 | 随机值(盐) | 不固定 | 强制 |
表 1.2.2:原始请求(类型 0x10)。从 表 1.1 中的加密请求中解密。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 | uint8 |
邮件类型 | 0x01 = 基于密钥的配对响应 |
1 - 6 个 | uint48 |
提供方的公共 (BR/EDR) 地址 | 不固定 |
7-15 人 | 随机值(盐) | 不固定 |
表 1.3:原始响应。加密,以生成 表 1.4. 中的加密响应。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 -15 | uint128 |
加密响应 | 不固定 |
表 1.4:加密响应,由提供程序通过“通知”发送给搜索者。
特征:通行密钥
基于密钥的配对过程中会使用此特性。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 15 | uint128 |
加密通行密钥屏蔽 | 不固定 |
表 2.1:加密通行密钥分块。如需了解用法,请参阅基于密钥的配对过程。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 | uint8 |
邮件类型 | 以下各项之一:
|
1-3 个 | unit32 |
6 位数通行密钥 | 不固定 |
4 - 15 人 | 随机值(盐) | 不固定 |
表 2.2:原始通行密钥块。 表 2.1. 的解密版本
特征:账号密钥
配对后,快速配对搜寻者会向快速配对提供程序写入一个账号密钥。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 15 | uint128 |
账号密钥(已加密) | 不固定 |
收到写入请求后,快速配对提供程序应执行以下操作:
- 使用根据过程第 4 步生成的共享密钥解密账号密钥。
- 对于需要绑定的 provider(通用):
- 在解密之前,请验证共享密钥是否用于解密第 12 步中的通行密钥请求。如果此步骤未使用此 Secret,请忽略此写入并退出。
- 此时,共享密钥(此过程中的 K)不会再次用于此配对。使用此密钥加密的任何请求都应被拒绝,而无需重启该过程。
- 对于需要绑定的 provider(通用):
- 验证解密后的值是否以
0x04
开头。如果没有,请忽略此写入并退出。 - 检查保留的帐号密钥列表是否为新值留出空间。
- 如果没有,请从列表中删除最近最少使用的值。
- 将新值添加到列表中。
列表中的账号密钥将在基于密钥的配对期间使用。
特征:固件修订
此特性使探索器能够根据需要读取提供程序的固件修订版本。它应始终返回以下数据:
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - var | utf8s |
固件修订代码 | 不固定 |
即使提供器上有多个固件(例如,针对左耳机、右耳机和充电盒提供 3 个固件),也应将其封装为单个 UTF8 字符串。 对于特殊情况,提供程序还可以返回特定字符串:
status-update:如果提供程序目前正在更新到新固件。 或者,提供商也可以返回预演固件的版本。
status-abnormal:如果提供程序处于异常状态。例如,由于固件更新失败,设备发生故障。此值将使探索器显示一条消息,让用户知道它现在必须更新。
提供程序应限制对固件修订版本特性的访问权限,以防止设备跟踪。建议的限制:
- 绑定的设备应该随时拥有访问权限
- 可检测到提供程序时,任何设备都应该具有访问权限
特征:其他数据
此服务应具有以下特征。
快速配对服务特征 | 已加密 | 权限 | 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 对其进行解码:
|
表 3.2:原始数据。从 表 3.1 中的加密数据中解密.
请求通知时(例如通过表 1.2.1 中的位 2 请求个性化名称),快速配对提供程序应执行以下操作:
- 为 Nonce 生成 8 个随机加密字节。
使用 AES-CTR 加密数据,其中每个 16 字节的块都是使用
encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
哪里
- AES 密钥是过程第 4 步的共享密钥。
- ClearBlock[i] 是一个 16 字节的块,从 data[i * 16] 开始。最后一个块可以小于 16 个字节。
执行 concat(加密块 [0], 加密块 [1],...) 以创建加密数据。
HMAC-SHA256 生成方式
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))
哪里
- K 由 concat(shared_secret, 48 个字节 ZEROs) 生成,shared_secret 来自过程中的第 4 步。
- opad 是 64 字节的外填充,由值为
0x5C
的重复字节组成。 - ipad 为 64 字节的内部填充,由值为
0x36
的重复字节组成。
获取 HMAC-SHA256 的前 8 个字节作为数据数据包的前缀。
收到写入请求后,快速配对提供程序应执行以下操作:
- 通过检查 HMAC-SHA256 的前 8 个字节来验证数据的完整性。
使用 AES-CTR 解密加密的数据,其中每个分块都使用
clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
哪里
执行 concat(clearBlock[0], clearBlock[1],...) 以创建原始数据。