Формат відкритий навмисно: конфіденційність і цілісність дають шифрування та підпис запиту, а не невідомість розмітки. Фіксована структура і CRC32 дозволяють серверу дешево відкидати сміття до запису в сховище.
Рядки обрізаються по межі символу UTF-8. Сервер відхиляє пакет, якщо довжина більша за ліміт, рядок не є коректним UTF-8, кількість подій не збігається із заголовком або CRC32 не сходиться.
Що робить сервер
Домен перераховується з URL (eTLD+1), значення клієнта не використовується.
З URL і запиту вирізаються токени, паролі, e-mail і номери карток.
Події, старші за 7 днів, і з майбутнього (більше ніж 10 хвилин) відкидаються.
Країна визначається за IP з’єднання, ідентифікатор установки хешується окремо для кожного розширення.
Шифрування і підпис
envelope
sessionKey = random(32)
iv = random(12)
ciphertext = AES-256-GCM(sessionKey, iv, bucket)
ephemeral = X25519 — нова пара на кожен пакет
shared = X25519(ephemeral.private, extension.publicKey)
derivedKey = HKDF-SHA256(IKM = shared, salt = iv, info = "intentd-bucket-v1", 32)
encryptedKey = AES-256-GCM(derivedKey, iv, sessionKey) // 48 байтів
Схема не дає прямої секретності при подальшій компрометації приватного ключа розширення і не захищає від власника копії бандла: від перепакування захищають сесії на кожну установку, перевірка ID розширення та перевірки на сервері.