Czytanie ciągu TC: co stoi w 213 bitach nagłówka

Spis treści
Spory o zgody toczą się zwykle na twierdzeniach: baner jest tak skonfigurowany, lista dostawców jest aktualna, ciąg jest świeży. Wszystkie trzy są zapisane, w ciasteczku o nazwie euconsent-v2, i o żadne z nich nie trzeba się spierać – bo ciąg nie jest zaszyfrowany. Jest upakowany, a jego rozpakowanie nie wymaga klucza.
Poniżej opisana jest budowa tego pakunku. Warto ją znać nie dla niej samej, lecz dlatego, że odczytanie ciągu wyjaśnia w pół minuty to, co inaczej zamienia się w pytanie do dostawcy: czy CMP zapisało to, co obiecywał dialog, kiedy zrobiło to ostatnio i wobec której wersji listy dostawców.

Jak ciąg jest upakowany
Ciąg TC to sekwencja pól o stałej długości bitowej, zapisanych jedno po drugim, bez separatorów, a następnie zakodowanych w Base64 w wariancie bezpiecznym dla sieci – tym, który używa myślnika i podkreślenia zamiast dwóch znaków wymagających maskowania w adresie. Każdy znak niesie dokładnie sześć bitów.
Dlatego każdy napotkany ciąg TC zaczyna się literą C: pierwszym polem jest wersja o szerokości sześciu bitów, a wersja 2 zapisana na sześciu bitach to 000010, czyli znak na pozycji 2 alfabetu. Ciąg zaczynający się inaczej albo nie jest ciągiem TC, albo nie jest wersją 2 – i jedno, i drugie warto zauważyć, zanim odczyta się cokolwiek innego.
213 bitów nagłówka
Wszystko aż do dostawców leży w stałej kolejności i właśnie to czyni ciąg czytelnym bez biblioteki.
| Pole | Bity | Co rozstrzyga |
|---|---|---|
| Wersja | 6 | W praktyce zawsze 2; wszystko inne nie należy do tego formatu. |
| Utworzono, ostatnia zmiana | po 36 | Dziesiąte części sekundy od 1970 – wiek zgody, co do sekundy. |
| Numer CMP, wersja CMP | po 12 | Które CMP zapisało ciąg i w jakiej wersji. |
| Wersja listy dostawców | 12 | Wersja listy, z której zbudowano dialog. |
| Wersja polityki TCF | 6 | Od 4 ciąg podlega regułom TCF 2.2. |
| Cechy szczególne | 12 | Dokładna lokalizacja i skanowanie urządzenia, jako dwa z dwunastu możliwych bitów. |
| Cele, cele z interesem | po 24 | Jedenaście przypisanych celów, dwukrotnie: zgoda i uzasadniony interes. |
Wraz z numerem ekranu zgody, dwuliterowym językiem, znacznikiem specyfiki usługi i krajem wydawcy daje to 213 bitów. Od bitu 214 zaczynają się dostawcy i tam stała długość się kończy.
Dlaczego jeden ciąg jest krótki, a następny bez końca
Dostawcy zapisywani są na jeden z dwóch sposobów, a ciąg wybiera to osobno dla każdej sekcji. Albo jako pole bitowe, jeden bit na dostawcę aż do najwyższego numeru – co kosztuje 1200 bitów, jeśli lista tak daleko sięga, niezależnie od tego, ilu faktycznie udzielono zgody. Albo jako zakresy: liczba, a potem dla każdego zakresu początek i koniec po szesnaście bitów.
Kto zgadza się na wszystko, tworzy ciąg zwarty, bo cała lista zapada się w garść zakresów. Kto wybiera pięćdziesięciu dostawców z ośmiuset, tworzy ten długi, bo każdy pojedynczy wybór staje się własnym zakresem. Długość ciasteczka mówi więc coś o kształcie decyzji, a nic o tym, jak hojna ona była.
Co TCF 2.2 zamieniło w błąd
Trzy rzeczy warto sprawdzić w każdym ciągu, a wszystkie trzy wraz z wersją polityki 4 przeszły z kwestii wykładni w twarde reguły.
Uzasadniony interes nie jest już dopuszczalny dla celów 1, 3, 4, 5 i 6. Ciąg niosący te bity pochodzi albo sprzed tej zmiany, albo od CMP, które jej nie uwzględniło – a bit nie jest niewinny, bo dostawcy czytają go jako podstawę przetwarzania.
Cele od 12 do 24 istnieją w formacie, ale nie w specyfikacji. Ustawione tam bity oznaczają, że CMP zapisuje do pól, których nikt nie definiuje – to najwyraźniejszy znak wdrożenia zrobionego na własną rękę.
I wiek: znacznik zmiany stoi w ciągu, zgodę starszą niż trzynaście miesięcy da się więc rozpoznać po samym ciasteczku. Razem z wersją listy dostawców odpowiada to na pytanie, czy dialog prowadzi dostawców, o których odwiedzającego nigdy nie zapytano – bo lista rośnie, a ciąg zapisany wobec starszej wersji po prostu nie ma nic do powiedzenia o nowo dodanych.
Segmenty za segmentem głównym
Ciąg może nieść więcej niż jeden segment, rozdzielony kropkami, a każdy kolejny zaczyna się trzema bitami nazywającymi jego rodzaj. Rodzaj 1 wymienia dostawców ujawnionych na urządzeniu, rodzaj 3 niesie własne cele wydawcy – te, które witryna może dodać dla siebie. Rodzaj 2 był segmentem dostawców dozwolonych i w 2.2 odpadł.
Wszystko za pierwszą kropką jest zatem dobrowolne, a jego brak nie jest usterką. Usterką jest drugi segment, którego nie da się zdekodować, bo pośrednicząca usługa obcięła ciasteczko na granicy długości – to zwykłe wyjaśnienie ciągu, który czyta się czysto do pewnego miejsca, a potem się urywa.
Co da się dzięki temu wyjaśnić w praktyce
Trzy pytania pojawiają się niemal w każdej kontroli, a ciąg odpowiada na wszystkie trzy bez niczyjego udziału. Czy CMP zapisało to, co obiecywał dialog – przez porównanie bitów celów z podjętymi decyzjami. Czy układ jest aktualny – po wersji polityki i wersji listy dostawców. I czy odwiedzający prowadzony jest na decyzji z innej epoki – po znaczniku zmiany.
Odczyt ciągu nie zastępuje sprawdzenia samego dialogu i nie mówi, czy dostawca respektuje zapisaną decyzję. Pozwala jednak zastąpić trzy twierdzenia trzema informacjami, które można bezpośrednio odczytać. Zwykle wystarcza to do wyjaśnienia tej części sporu, która opierała się dotąd wyłącznie na twierdzeniach.
Pytania i odpowiedzi
Na co uważać przy ręcznym dekodowaniu ciągu TC bez biblioteki?
Na trzy miejsca, w których zwykłe narzędzia się potykają. Pierwsze to alfabet: Base64 w wariancie bezpiecznym dla sieci używa myślnika i podkreślenia tam, gdzie wiele standardowych dekoderów oczekuje plusa i ukośnika. Oba znaki trzeba wtedy wcześniej podmienić, a brakujące dopełnienie znakami „=” uzupełnić, aż długość będzie podzielna przez cztery.
Drugie to jednostka. Dekoder Base64 zwraca bajty, a pola ciągu nie trzymają się granic bajtów: wersja zajmuje sześć bitów, oba znaczniki czasu po 36. Wygodniej jest więc przełożyć każdy znak bezpośrednio na sześć bitów według jego pozycji w alfabecie, bo właśnie tak ciąg jest zbudowany; podmiana znaków i dopełnienie przestają wtedy mieć znaczenie. Pola są potem odliczane kolejno w jednym długim szeregu zer i jedynek.
Trzecie to granica nagłówka. 213 bitów to 35,5 znaku, nagłówek kończy się więc w połowie 36. znaku, a jego ostatnie trzy bity należą już do części z dostawcami. Kto odetnie tylko pierwsze 35 znaków, straci koniec nagłówka; kto weźmie 36, przeczyta trzy bity za dużo. Kropki rozdzielają przy tym segmenty i nie należą do Base64, każdy segment jest więc dekodowany osobno.
Co, jeśli na stronie nie ma ciasteczka euconsent-v2?
Wtedy ciąg leży gdzie indziej albo nazywa się inaczej. Framework nie narzuca miejsca przechowywania, a euconsent-v2 to jedynie rozpowszechniona nazwa. Pewniejszy jest interfejs, który każde CMP zgodne z TCF musi udostępniać w przeglądarce: wywołanie __tcfapi('getTCData', 2, d => console.log(d.tcString)) w konsoli zwraca aktualny ciąg w polu tcString, niezależnie od tego, gdzie CMP go przechowuje.
Po czym rozpoznać obcięty ciąg, zanim któryś segment stanie się nieczytelny?
Po rachunku, na który pozwala sam ciąg. Po bicie 213 w segmencie głównym znajduje się najpierw najwyższy numer dostawcy objęty tą sekcją, a potem znacznik, czy dalej idzie pole bitowe, czy zakresy. Przy polu bitowym wiadomo więc, ile bitów zajmuje sekcja: jeden na każdego dostawcę aż do tego numeru. Jeśli reszta ciągu jest krótsza, czegoś brakuje. Przy zakresach liczba podana z góry mówi, ile wpisów nastąpi, a przejście przez nie pokazuje, czy ciąg nie kończy się przed ostatnim.
Jako przyczyny wchodzą w grę dwie granice. Przeglądarki muszą według RFC 6265 obsługiwać co najmniej 4096 bajtów na ciasteczko, liczonych łącznie z nazwą, wartością i atrybutami; serwery i usługi pośredniczące ograniczają ponadto rozmiar nagłówków żądania, w których wszystkie ciasteczka domeny podróżują razem. Ciąg kończący się tuż przy takiej granicy jest podejrzany, nawet jeśli segment główny czyta się jeszcze w całości.