提供方通告信号
通告:可检测到时
当提供方设备处于 BR/EDR 可检测到状态(即配对模式)时,它应通过 BLE 广播快速配对模型 ID 数据,并且 BLE 地址不应轮替。
通告间隔:可检测到时
通告之间的间隔不应大于 100 毫秒 (10Hz)。快速扫描可让 Seeker 快速找到 Provider,即使在低功耗模式下扫描也是如此。
广告载荷:快速配对模型 ID 数据
通告应包含服务数据数据类型(同上),§ 1.11. UUID 应为快速配对服务 UUID 0xFE2C。服务数据应包含以下内容:
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0-2 | uint24 |
24 位模型 ID | 视情况而定 |
LE 音频分享广播载荷:快速配对模型 ID 数据和快速配对功能映射
服务数据应包含以下内容:
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0 | uint8 |
版本和标志 0bVVVVFFFF
|
0x00 |
| 1 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0bLLLL0111
|
| 2 - s | 模型 ID | 视情况而定 | |
| s + 1 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0bLLLL1000
|
| s + 2 | uint8 |
指纹功能映射 | 视情况而定 |
指纹功能映射
FP 功能映射是一个位图,表示提供程序支持哪些 FP 功能。位图的第一个字节定义如下:
| 位图 | 说明 |
|---|---|
| 0bRRRRRRSO | R - 预留位,目前会被 seeker 忽略,应设置为 0。 S - FP LE 音频分享支持(如果已启用,则设置为 1,否则设置为 0)。 O - 开箱即用 (OOB) 位,如果设备是全新出厂,则设置为 1。 |
如果提供方支持 FP LE 音频分享规范(即支持临时配对、LE 音频分享通告载荷和可穿戴设备控制版本 2),请将 FP LE 音频分享支持位设置为 1;否则,请将其设置为 0。
如果提供方未与任何 FP 寻觅方配对,并且是出厂新设备(即提供方上没有 FP 账号密钥),请将 OOB 位设置为 1;否则,请将其设置为 0。
协调集信息广告载荷:快速配对模型 ID 数据和 FP 协调集信息
服务数据应包含以下内容:
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0 | uint8 |
版本和标志 0bVVVVFFFF
|
0x00 |
| 1 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0bLLLL0111
|
| 2 - s | 模型 ID | 视情况而定 | |
| s + 1 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0b01101011
|
| s + 2 - s + 7 | uint48 |
FP 协调集数据 | 6 字节数据,请参阅快速配对协调集信息 |
FP 协调集信息
FP 协调集信息用于识别广告设备是否在同一协调集中。
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0 | uint8 |
协调套装尺寸 | 不定 |
| 1 | uint8 |
快速配对协调集成员类型 | 可以是以下值之一
|
| 2 - 5 | uint32 |
设置身份解析密钥哈希 | 不定 |
用于生成 Set Identity Resolving Key 的哈希值的算法为
使用 SHA256 对 SIRK 值进行哈希处理
SIRK = 0xe3b0c44298fc1c149afbf4c8996fb924SHA256(SIRK) = 0x2646036bb22781536be710245c8cbb04b92842c587f845996ce8ab542592a25e提取前四个字节作为哈希值
Hash Value of Set Identity Resolving Key = 0x2646036b
如需了解设置身份解析密钥,请参阅协调集标识服务。
通告:不可检测到时
当不可检测到(即不处于配对模式)时,提供方设备应按照以下准则通告快速配对账号数据。
通过通告账号数据,附近的 Seekers 可以识别 Provider 何时属于其账号,并启动配对,而无需先强制 Provider 返回配对模式,这是用户投诉的常见原因。如果用户不想与提供方配对,或者广播不相关(例如,如果他们已经配对),则搜索方将为用户提供忽略此广播的机会。 Seeker 还会自动滤除明显错误的广播,例如账号数据配置错误。
通告间隔:不可检测到时
通告之间的间隔时间不应超过 250 毫秒 (4Hz)。
通告载荷:快速配对账号数据
通告应包含服务数据数据类型,同上,§ 1.11. UUID 应为快速配对服务 UUID 0xFE2C。服务数据应包含以下内容:
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0 | uint8 |
版本和标志 0bVVVVFFFF
|
0x00(预留以供日后使用) |
| 1 - 各不相同 | 账号密钥数据 | 视情况而定 |
账号密钥数据包含:
| 八位字节 | 数据类型 | 说明 | 值 |
|---|---|---|---|
| 0 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0bLLLL0000
|
| 1 - s | 账号密钥过滤条件 | 视情况而定 | |
| s + 1 | uint8 |
字段长度和类型 0bLLLLTTTT
|
0b00100001
|
| s + 2 - s + 3 | uint16 |
Salt | 视情况而定 |
账号密钥过滤条件
通过广播的账号密钥过滤器,Seeker 可以在进一步互动之前快速检查 Provider 是否可能拥有特定账号密钥(假正例概率较低,平均远低于 0.5%)。当 Seeker 看到正在广播的过滤器的类型为 0(即显示界面指示,可能包含其某个账号密钥)时,可能会自动连接并尝试启动该过程,以便进一步降低误报率。在某些情况下,提供方可能希望被发现方识别,但尚未准备好配对。例如,当耳机放回充电盒时,我们希望停止显示后续配对通知,因为该配对可能会被耳机拒绝。
账号密钥过滤器是一个可变长度的布隆过滤器,其构造如下:
- 假设 n 是持久化账号密钥列表中的账号密钥数量 (n >= 1)。
- 假设 s(过滤条件的大小,以字节为单位)为 (1.2*n + 3) 截断。例如,如果保留 1 个密钥,则 s = 4 字节。
uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3); - 将过滤器 F 初始化为 s 字节的数组,每个字节都设置为 0。
uint8_t F[s] = {0}; 对于永久性账号密钥列表中的每个账号密钥 K:
a. 假设 V 为 concat(K, Salt)。// In the sample code, the size of salt is 2 bytes. #define SALT_SIZE 2 uint8_t V[FASTPAIR_ACCOUNT_KEY_SIZE + SALT_SIZE]; for (uint8_t keyIndex = 0; keyIndex < n; keyIndex++) { // concat (K, Salt) fastpair_get_account_key_by_index(keyIndex, V); uint8_t randomSalt = (uint8_t)rand(); V[FASTPAIR_ACCOUNT_KEY_SIZE] = randomSalt; ... }b. 使用 SHA256 对 V 进行哈希处理,获得 32 字节值 H = {H0, …, H31}。
uint8_t H[32] = {0}; SHA256_hash_function(V, H);c. 将 H 划分为 8 个大端序 4 字节无符号整数,X = {X0, …, X7},其中 X0 = 0xH0H1H2H3。
uint32_t X[8]; for (index = 0; index < 8; index++) { X[index] = (((uint32_t)(H[index * 4])) << 24) | (((uint32_t)(H[index * 4 + 1])) << 16) | (((uint32_t)(H[index * 4 + 2])) << 8) | (((uint32_t)(H[index * 4 + 3])) << 0); }d. 对于每个 Xi:
i. 假设 M 为 Xi 模过滤器中的位数 (s * 8)。
ii. 获取 F 中索引为 (M / 8) 的字节(向下舍入)。
iii. 在该字节内,将索引 (M % 8) 处的位设置为 1。
iv. 也就是说:// M = Xi % (s * 8) // F[M/8] = F[M/8] | (1 << (M % 8)) for (index = 0; index < 8; index++) { uint32_t M = X[index] % (s * 8); F[M / 8] = F[M / 8] | (1 << (M % 8)); }
在广告数据中,将过滤条件 F 作为“账号密钥过滤条件”字段。 请注意,此值没有“字节序”,因为没有更重要或更不重要的字节,请勿更改字节顺序。
盐田
盐值是一个随机值,在构建布隆过滤器时会附加到账号密钥中。每次为提供方更新 RPA 时,都应重新生成此盐,以避免在地址轮替期间进行跟踪。
如需使用盐生成账号密钥过滤器,请执行以下操作:
- 生成一个随机的 2 字节 S。请注意,此值没有“字节序”,因为没有更重要或更不重要的字节,请勿更改字节顺序。
- 使用 2 字节 S 作为盐。
- 在通告的快速配对账号数据中,在“账号密钥过滤器”字段中添加生成的过滤器,并在“盐”字段中添加 S。