特性
快速配对服务
快速配对提供商应提供以下 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
此特征允许 Seeker 根据需要读取模型 ID, 当设备以可检测到模式进行通告时触发。它应该始终返回 以下数据:
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 2 人 | uint24 |
模型 ID | 不定 |
特性:基于密钥的配对
此特性控制基于密钥的配对过程。在此过程中 通过验证寻找者和 提供方均拥有预共享密钥。键的区别在于 :
案例 1:预共享密钥基于防仿冒公钥/私钥 和搜寻者自己的公钥/私钥对, 配对尝试。
- 提供程序处于配对模式。
- 寻找者验证提供者是否拥有 防仿冒私钥
请注意,在配对模式下,提供程序当然也可以在配对模式下 例如与不支持快速响应功能的设备配对 基于密钥的配对。
案例 2:预共享密钥是账号密钥之一。
- 提供程序通常不处于配对模式。(但这不是 要求—提供商应支持使用账号密钥,即使在 配对模式)。
- 寻找者和提供者各自验证对方是否拥有 账号密钥。
由于这两种情况极其相似,除了使用预共享密钥之外, 它们会在程序中合并。
数据格式
如需了解每种格式的使用方法,请参阅过程。
八位字节 | 数据类型 | 说明 | 值 | 是否必需? |
---|---|---|---|---|
0 - 15 | uint128 |
已加密的请求 | 不定 | 强制 |
16-79 人 | 公钥 | 不定 | 可选 |
表 1.1:加密请求,由 Seeker 写入该特性。
八位字节 | 数据类型 | 说明 | 值 | 是否必需? |
---|---|---|---|---|
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 - n | 附加数据 | 因人而异 | 可选 | |
n - 15 | 随机值(盐) | 因人而异 | 强制 |
表 1.2.2:原始请求(类型 0x10)。从已加密的 表 1.1 中的请求。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 | uint8 |
邮件类型 | 0x01 = 基于密钥的配对响应 |
1 - 6 人 | uint48 |
提供方的公开 (BR/EDR) 地址 | 因人而异 |
7-15 人 | 随机值(盐) | 因人而异 |
表 1.3:原始响应。已加密以在 中生成 Encrypted Response 表 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 |
账号密钥(已加密) | 因人而异 |
收到写入请求时,快速配对提供程序应执行以下操作:
- 使用在
流程。
- 对于需要绑定(通用)的提供商:
<ph type="x-smartling-placeholder">
- </ph>
- 在解密之前,请验证已使用共享密钥解密 第 12 步中的通行密钥请求。如果此步骤尚未通过 Secret,请忽略此写入并退出。
- 此时,系统不会使用共享密钥(过程中的 K) 使用此密钥加密的所有请求 而不会重新开始该程序。
- 对于需要绑定(通用)的提供商:
<ph type="x-smartling-placeholder">
- 验证解密后的值是否以
0x04
开头。如果没有,则忽略 写入并退出。 - 检查保留的账号密钥列表是否有足够的空间存储新的 值。
- 如果不是,请从列表中删除最近最少使用的值。
- 将新值添加到列表中。
列表中的账号密钥会在基于密钥的配对期间使用。
特征:固件修订版本
此特性允许 Seeker 读取 提供商。它应始终返回以下数据:
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 变量 | utf8s |
固件修订版本代码 | 因人而异 |
即使有多个 utf8 字符串,也应将其封装为单个 utf8 字符串 (例如,左侧耳机、右侧耳机和充电盒的 3 个固件)。 对于特殊情况,提供程序还可以返回特定字符串:
status- updates:如果提供程序当前正在更新到新固件。 或者,提供程序也可以返回暂存固件的版本。
status-abnormal:如果提供程序处于异常状态。例如, 因为固件更新失败而出现故障。该值会导致 Seeker 显示一条消息,让用户知道必须立即更新该消息。
提供商应将对固件修订版本特性的访问权限限制为 阻止设备跟踪。建议的限制:
- 绑定的设备应该有权随时访问
- 当提供程序可检测到时,任何设备都应该有权访问
特征:其他数据
此服务应具有以下特征。
快速配对服务特征 | 已加密 | 权限 | 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 - 变量 | 加密的数据。 | 因人而异 |
表 3.1:提供程序通过 通过写入通知或发送给提供程序。
八位字节 | 数据类型 | 说明 | 值 |
---|---|---|---|
0 - 变量 | byte array |
数据 | ,则根据表 1.2.2 的数据 ID 进行解码:
|
表 3.2:原始数据。从以下项目的加密数据中解密: 表 3.1.
请求通知时(例如,通过 表 1.2.1),快速配对提供程序应执行以下操作:
- 为 Nonce 生成 8 个加密随机字节。
使用 AES-CTR 加密数据,其中每个 16 个字节的块都使用
encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
其中
- AES 密钥是过程中第 4 步中的共享密钥。
- clearBlock[i] 是一个从 data[i * 16] 开始的 16 字节块。最后一个 可以小于 16 个字节。
执行 concat(encryptedBlock[0], encryptionBlock[1],...) 创建 加密数据。
HMAC-SHA256 的生成依据
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))
其中
- K 由 concat(shared_secret, 48 字节 ZERO) 生成, shared_secret 将在过程中的第 4 步中找到。
- opad 是 64 个字节的外部填充,由输入的重复字节组成
0x5C
。 - ipad 是 64 个字节的内部填充,由输入的重复字节组成
0x36
。
将 HMAC-SHA256 中的前 8 个字节作为 Data 数据包。
收到写入请求时,快速配对提供程序应执行以下操作:
- 通过检查 HMAC-SHA256。
使用 AES-CTR 解密已加密的数据,其中每个分块都使用
clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
其中
执行 concat(clearBlock[0], clearBlock[1],...) 创建原始数据。