Формат открыт намеренно: конфиденциальность и целостность дают шифрование и подпись запроса, а не неизвестность разметки. Фиксированная структура и 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 расширения и проверки на сервере.