Canvas fingerprinting dincolo de elementele de bază: de ce două browsere Chrome identice randează pixeli diferiți
Două dispozitive cu același Chrome, OS și GPU tot randează pixeli canvas diferiți. De ce randarea este nedeterministă, de ce zgomotul pentru confidențialitate se întoarce împotriva ta și unde se încadrează canvas în detecție.
Canvas fingerprinting este folosit în producție încă din 2012. Ideea este simplă: ceri browserului să randeze conținut 2D, citești înapoi pixelii și îi transformi într-un hash. Dispozitive diferite produc pixeli ușor diferiți pentru aceleași instrucțiuni, iar acele diferențe sunt suficient de stabile pentru a identifica un dispozitiv de-a lungul sesiunilor.
Atât se știe bine. Ce se înțelege mai puțin este de ce funcționează tehnica — de ce configurații software identice pe hardware identic produc totuși ieșiri de pixeli diferite. Răspunsul se află la intersecția dintre driverele GPU, randarea fonturilor și aritmetica în virgulă mobilă.
Pipeline-ul de randare nu este determinist
Când JavaScript apelează context.fillText("Cwm fjord bank glyphs vext quiz", 4, 45), Chrome nu randează el însuși pixelii. Generează instrucțiuni pentru Skia — biblioteca grafică 2D — care la rândul ei emite comenzi de desenare către un backend accelerat pe GPU (de obicei ANGLE pe Windows, Metal pe macOS sau fallback software în containere).
La fiecare pas se acumulează mici diferențe de implementare:
-
Subsistemul de fonturi al Skia selectează o familie de fonturi. Dacă Arial nu este instalat, se recurge la un fallback — iar acest fallback variază în funcție de fonturile instalate în sistem.
-
Fontul selectat este randat la dimensiunea cerută folosind FreeType (pe Linux), DirectWrite (pe Windows) sau Core Text (pe macOS). Fiecare bibliotecă are algoritmi de hinting diferiți.
-
Se aplică poziționarea la nivel de subpixel. Aici încep fonturile identice să producă pixeli diferiți — algoritmul rotunjește pozițiile la offset-uri fracționare de pixel, iar regulile de rotunjire diferă între platforme.
-
Textul rasterizat este compus pe canvas. Amestecarea (blending) se face cu shadere GPU pe sistemele accelerate hardware și cu cod CPU în modul fallback.
Fiecare dintre acești pași poate introduce diferențe de una sau două valori de pixel. Individual, invizibile. Colectiv, unice.
Versiunile de driver GPU domină fingerprint-ul
Două mașini Windows 11 cu cipuri Intel UHD Graphics 620 pot produce ieșiri canvas diferite dacă driverele lor GPU diferă. Intel livrează actualizări de driver de mai multe ori pe an, iar fiecare actualizare poate schimba filtrarea la nivel de subpixel, corecția gamma și anti-aliasing-ul textului.
Asta înseamnă că stabilitatea fingerprint-ului canvas este limitată de frecvența actualizărilor de driver. Un utilizator care își actualizează driverul grafic — adesea în tăcere, prin Windows Update — își va vedea fingerprint-ul canvas schimbându-se.
Sistemele de detecție tratează acest lucru considerând fingerprint-ul canvas drept unul dintre multele semnale, nu un identificator de sine stătător. Când se schimbă, dar alte semnale rămân stabile (fingerprint TLS, WebGL renderer, fusul orar, fonturile instalate), vizitatorul este în continuare recunoscut.
Randarea emoji este o mină de aur
Elementul cel mai identificator al unui fingerprint canvas nu este adesea textul sau formele, ci emoji-urile. Randarea emoji depinde de fontul emoji livrat cu OS-ul — Segoe UI Emoji pe Windows, Apple Color Emoji pe macOS, Noto Color Emoji pe Android.
Chiar și în cadrul aceluiași OS, randarea emoji se schimbă între versiuni. Randarea unui emoji curcubeu în Windows 10 diferă de cea din Windows 11. Fața zâmbitoare din iOS 16 are un anti-aliasing diferit de cel din iOS 17.
Scripturile moderne de canvas fingerprinting randează în mod specific secvențe de emoji, inclusiv adăugiri noi la Unicode. Un vizitator care pretinde că rulează Safari pe iPhone, dar care nu poate randa un emoji adăugat în iOS 17, rulează un iOS mai vechi — sau minte în privința platformei.
Framework-urile de automatizare produc fingerprint-uri distinctive
Chrome headless, rulând într-un container Docker fără GPU, folosește SwiftShader pentru randare. SwiftShader produce ieșiri canvas care sunt consistente intern, dar distincte de orice Chrome accelerat hardware.
Semnătura este recognoscibilă: anti-aliasing neobișnuit de curat, valori de culoare specifice în regiunile de gradient și margini de text care nu se potrivesc cu niciun driver GPU cunoscut. Un fingerprint canvas care se potrivește cu SwiftShader în Chrome 124 într-un container Linux este aproape sigur automatizare — niciun utilizator real nu rulează un browser în acest fel.
Puppeteer-extra-stealth încearcă să falsifice ieșirea canvas interceptând toDataURL() și returnând date modificate. Dar modificarea introduce adesea propriile artefacte — tipare de zgomot care se repetă între sesiuni, ceea ce paradoxal face efortul anti-fingerprinting mai ușor de detectat decât dacă nu s-ar fi făcut nimic.
De ce injectarea de zgomot nu funcționează bine
Browserele axate pe confidențialitate, precum Brave, injectează zgomot în ieșirea canvas pentru a preveni urmărirea. Ideea este de a adăuga mici variații aleatorii valorilor pixelilor, astfel încât același dispozitiv să producă fingerprint-uri diferite la fiecare sesiune.
În practică, injectarea de zgomot are trei probleme:
1. Zgomotul în sine este un fingerprint. Un vizitator a cărui ieșire canvas se schimbă la fiecare încărcare, dar ale cărui alte semnale rămân identice, este recognoscibil ca browser care injectează zgomot. Asta în sine este identificator.
2. Algoritmul de zgomot este stabil. Implementarea Brave produce tipare de zgomot specifice care nu se potrivesc cu varianța naturală a randării GPU. Sistemele de detecție pot identifica ieșirile canvas care par cu zgomot injectat față de cele care par naturale.
3. Sistemele sofisticate combină eșantioane. Mai multe randări pe aceeași pagină, sau de-a lungul sesiunilor, pot fi mediate. Dacă zgomotul este mic, media converge către fingerprint-ul determinist de bază.
Ce captează canvas fingerprinting
Dincolo de ieșirea vizuală evidentă, canvas fingerprinting poate extrage câteva atribute ale dispozitivului ca efecte secundare:
Timpul de randare — cât durează randarea canvas dezvăluie capacitatea GPU. Un desktop 4K cu un GPU discret randează mai repede decât un laptop de gamă medie.
Metricile de text — measureText() returnează lățimi exacte în pixeli care variază în funcție de randarea fontului. Lățimea textului poate fi folosită ca fingerprint chiar și fără randare.
Suportul pentru operații de compunere — unele browsere sau configurații GPU suportă moduri de compunere extinse. Testarea suportului dezvăluie limitele de capacitate.
Efectele de filtru — filtrele în stil CSS aplicate pe canvas produc ieșiri diferite între GPU-uri, în special filtrele de blur și drop-shadow.
Unde se încadrează canvas fingerprinting într-un stack de detecție
De unul singur, canvas fingerprinting nu este un identificator robust. Driverele se schimbă. Utilizatorii schimbă browserele. Injectarea de zgomot este frecventă în audiențele preocupate de confidențialitate.
Adevărata sa putere este ca verificare încrucișată. Când o sesiune pretinde că aparține unui utilizator care revine, pe baza cookie-urilor sau a autentificării în cont, fingerprint-ul canvas acționează ca al doilea semnal — potrivirea cu fingerprint-ul istoric confirmă afirmația, iar nepotrivirea semnalează un account takeover sau un session hijacking.
Pentru bot detection, canvas fingerprinting excelează la prinderea automatizării în containere. Utilizatorii reali au GPU-uri reale. GPU-urile reale produc semnături de randare recognoscibile. Orice randează ca SwiftShader, sau ca un canvas prost falsificat, se încadrează în categoria aproape sigur bot.
Tehnica din 2012 funcționează încă în 2026 din același motiv: randarea este deterministă pentru fiecare mediu, dar aproape imposibil de falsificat complet. Fiecare încercare de a te ascunde lasă urme ale încercării în sine.