Рекламный сигнал провайдера

Реклама: когда ее можно обнаружить

Когда устройство поставщика доступно для обнаружения BR/EDR (то есть в режиме сопряжения), оно должно объявлять данные идентификатора модели быстрой пары через BLE, и адрес BLE не должен меняться.

Интервал рекламы: Когда можно обнаружить

Интервал между рекламными объявлениями должен быть не более 100 мс (10 Гц). Высокая скорость позволяет Искателю быстро найти Провайдера даже при сканировании в режиме пониженного энергопотребления.

Рекламная нагрузка: данные идентификатора модели быстрой пары.

Рекламное объявление должно содержать тип данных «Сервисные данные», там же, § 1.11. UUID должен быть UUID службы быстрого сопряжения 0xFE2C . Служебные данные должны содержать следующее:

Октет Тип данных Описание Ценить
0-2 uint24 24-битный идентификатор модели варьируется

Реклама: когда ее невозможно обнаружить

Если устройство поставщика не обнаруживается (то есть не находится в режиме сопряжения), оно должно публиковать данные учетной записи быстрого сопряжения, используя следующие рекомендации.

Объявление данных учетной записи позволяет Искателям поблизости распознавать, когда провайдер принадлежит их учетной записи, и инициировать сопряжение без необходимости сначала принудительно возвращать провайдера в режим сопряжения, что является распространенной причиной жалоб пользователей. Искатели предоставят возможность пользователям игнорировать эту трансляцию в случае, если они не ждут сопряжения с провайдером или трансляция не актуальна (например, если они уже выполнили сопряжение). Искатели также будут автоматически отфильтровывать явно плохие трансляции, например, когда данные учетной записи неправильно настроены.

Интервал рекламы: когда невозможно обнаружить

Интервал между рекламными объявлениями должен составлять не более 250 мс (4 Гц).

Рекламная нагрузка: данные учетной записи Fast Pair

Рекламное объявление должно содержать тип данных «Сервисные данные», Там же, § 1.11. UUID должен быть UUID службы быстрого сопряжения 0xFE2C . Служебные данные должны содержать следующее:

Октет Тип данных Описание Ценить
0 uint8 Версия и флаги
0бВВВВФФФФ
  • В = версия
  • F = флаги
0x00
(зарезервировано для будущего использования)
1 - варьируется Ключевые данные учетной записи варьируется
или 0x00 , если список ключей учетной записи пуст.

Ключевые данные учетной записи содержат:

Октет Тип данных Описание Ценить
0 uint8 Длина и тип поля
0bLLLLTTTT
  • L = длина фильтра ключей учетной записи в байтах
  • Т = тип
0bLLLL0000
  • длина = 0bLLLL = варьируется
  • type = 0b0000 (показать индикацию пользовательского интерфейса) или 0b0010 (скрыть индикацию пользовательского интерфейса), Фильтр ключей учетной записи
1 - с Фильтр ключей учетной записи варьируется
с + 1 uint8 Длина и тип поля
0bLLLLTTTT
  • L = длина в байтах
  • Т = тип
0b00100001
  • длина = 0b0010 = 2
  • тип = 0b0001, Соль
с + 2 - с + 3 uint16 Соль варьируется

Фильтр ключей учетной записи

Рекламируемый фильтр ключей учетной записи позволяет Искателю быстро проверить, может ли Провайдер обладать определенным ключом учетной записи (с низкой вероятностью ложного срабатывания, в среднем намного меньше 0,5%), перед дальнейшим взаимодействием. Искатель может автоматически подключиться и попытаться запустить процедуру, когда он увидит широковещательный фильтр с типом 0, т. е. показывающий индикацию пользовательского интерфейса, который потенциально содержит один из ключей его учетной записи, чтобы еще больше снизить уровень ложных срабатываний. В некоторых ситуациях Поставщик может захотеть, чтобы Искатель узнал его, хотя он еще не готов к сопряжению. Одним из примеров является то, что когда наушники возвращаются в футляр, мы хотим перестать показывать последующее уведомление о сопряжении, поскольку это сопряжение может быть отклонено гарнитурой.

Фильтр ключа учетной записи — это фильтр Блума переменной длины, построенный следующим образом:

  1. Пусть n — количество ключей учетной записи ( n >= 1) в сохраненном списке ключей учетной записи .
  2. Пусть s , размер фильтра в байтах, будет усечен (1,2* n + 3). Например, если сохраняется 1 ключ, s = 4 байта.
    uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3);
  3. Инициализируйте фильтр F как массив из s байтов, каждый из которых установлен в 0.
    uint8_t F[s] = {0};
  4. Для каждого ключа учетной записи K в постоянном списке ключей учетной записи :
    а. Пусть 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;
          ... }
    

    б. Хэшируйте V с использованием SHA256, получая 32-байтовое значение H = {H 0 , …, H 31 }.

    uint8_t H[32] = {0};
    SHA256_hash_function(V, H);
    

    в. Разделите H на восемь 4-байтовых целых чисел без знака в обратном порядке, X = {X 0 , …, X 7 }, где X 0 = 0xH 0 H 1 H 2 H 3 .

         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);
         }
    

    д. Для каждого Xi :
    я. Пусть M будет X i по модулю количества бит в фильтре ( 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 обновляется для поставщика, чтобы избежать отслеживания ротации адресов.

Чтобы создать фильтр ключей учетной записи с использованием соли:

  1. Сгенерируйте случайный 2-байтовый S . Обратите внимание, что для этого значения нет «порядка байтов», поскольку нет более или менее значимого байта — не меняйте порядок байтов.
  2. Используйте 2-байтовый S в качестве соли.
  3. В объявленных данных учетной записи Fast Pair включите сгенерированный фильтр в поле «Фильтр ключа учетной записи» и S в поле «Соль».