供應商廣告信號
廣告:可供發現的時間
當提供者裝置可供 BR/EDR 偵測 (也就是處於配對模式) 時,應透過 BLE 宣傳快速配對型號 ID 資料,且不得輪替 BLE 位址。
廣告間隔:可供探索時
廣告之間的間隔不得超過 100 毫秒 (10 Hz)。快速率可讓 Seeker 快速找到 Provider,即使在低耗電量模式下掃描也一樣。
廣告酬載:Fast Pair 型號 ID 資料
廣告必須包含「服務資料」資料類型,同上,§ 1.11. UUID 應為 0xFE2C
的快速配對服務 UUID。服務資料應包含下列項目:
Octet | 資料類型 | 說明 | 值 |
---|---|---|---|
0-2 | uint24 |
24 位元型號 ID | 視情況而定 |
廣告:無法偵測
在無法偵測的情況下 (也就是不在配對模式),供應器裝置應使用以下規範宣傳快速配對帳戶資料。
宣傳帳戶資料可讓附近的尋找者在提供者屬於自己的帳戶時,直接啟動配對程序,而不需要先強制將提供者設回配對模式,這也是使用者常見的抱怨原因。當使用者不想等待與供應商配對,或是廣播內容不相關 (例如,如果他們已配對) 時,Seeker 會提供機會讓使用者忽略這項廣播。Seeker 也會自動篩除明顯不良的廣播,例如帳戶資料設定錯誤的情況。
廣告間隔:無法偵測到時
廣告間隔應不超過 250 毫秒 (4Hz)。
廣告酬載:快速配對帳戶資料
廣告應包含「服務資料」資料類型,同上,§ 1.11. UUID 應為 0xFE2C
的快速配對服務 UUID。服務資料應包含下列項目:
Octet | 資料類型 | 說明 | 值 |
---|---|---|---|
0 | uint8 |
版本和標記 0bVVVVFFFF
|
0x00 (保留供日後使用) |
1 - 視情況而定 | 帳戶金鑰資料 | 視情況而定 |
帳戶主要資料包含:
Octet | 資料類型 | 說明 | 值 |
---|---|---|---|
0 | uint8 |
欄位長度和類型 0bLLLLTTTT
|
0bLLLL0000
|
1 - 秒 | 帳戶金鑰篩選器 | 視情況而定 | |
s + 1 | uint8 |
欄位長度和類型 0bLLLLTTTT
|
0b00100001
|
s + 2 - s + 3 | uint16 |
Salt | 視情況而定 |
帳戶金鑰篩選器
廣告中的帳戶金鑰篩選器可讓尋求者快速檢查提供者是否可能擁有特定帳戶金鑰 (平均而言,誤判為正確的機率低於 0.5%),然後再進一步互動。當 Seeker 發現以 0 型式廣播的篩選器 (即顯示 UI 指示,可能包含其中一個帳戶金鑰),就可能自動連線並嘗試啟動程序,以進一步降低誤判率。在某些情況下,提供者可能不想配對,但希望 Seeker 能辨識。舉例來說,當耳機放回充電盒時,我們會停止顯示後續配對通知,因為耳機可能會拒絕配對。
帳戶金鑰篩選器是可變長度的 Bloom 篩選器,其建構方式如下:
- 假設 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 以大端序分成八個 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 是 X 除以篩選器中的位元數,即 (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 設為「帳戶金鑰篩選器」欄位。請注意,此值沒有「endianness」,因為沒有較大或較小的位元組,因此請勿變更位元組順序。
鹽田
鹽值是隨機值,會在建構布隆過濾器時附加至帳戶金鑰。每次為供應者更新 RPA 時,都應重新產生此鹽值,以免在地址輪替期間追蹤。
如要使用鹽值產生帳戶金鑰篩選器,請按照下列步驟操作:
- 產生隨機 2 位元組 S。請注意,這個值沒有「endianness」,因為沒有較大或較小的位元組,因此請勿變更位元組順序。
- 使用 2 個位元組的 S 做為 Salt。
- 在宣傳的「快速配對帳戶資料」中,請在「帳戶金鑰篩選器」欄位中加入產生的篩選器,並在「Salt」欄位中加入 S。