Back to blog

Sådan fungerer hash-baseret besøgsidentifikation (og hvorfor den er privatlivsvenlig)

En teknisk dybdegående gennemgang af, hvordan moderne cookiefri analyseværktøjer identificerer unikke besøgende uden at lagre noget på deres enheder, ved hjælp af daglige roterende kryptografiske hashes.

Problemet: at tælle unikke besøgende uden at spore dem

At tælle unikke besøgende er et af de ældste problemer i webanalyse. Du vil vide, hvor mange forskellige personer der kom til dit site i går, hvor mange der kom tilbage i dag, og hvor mange der ankom for første gang fra en bestemt kampagne. Det er rimelige spørgsmål for enhver, der driver et website. At besvare dem kræver en eller anden måde at sige: "Disse to sidevisninger kom fra den samme person, og disse to gjorde ikke."

I årtier var standardsvaret at give hver besøgende en permanent identifikator — normalt lagret i en cookie — og slå den identifikator op ved hver forespørgsel. En ny besøgende får et nyt ID. En tilbagevendende besøgende genbruger sit. At tælle unikke er så blot et spørgsmål om at tælle distinkte ID'er.

Den tilgang fungerer smukt for ingeniøren og forfærdeligt for den besøgende. En permanent identifikator, lagret på enheden, knyttet til hver forespørgsel, er præcis den slags, som ePrivacy-direktivet blev skrevet for at kontrollere. Det kræver samtykke i EU, og det skaber et reelt privatlivsproblem, selv når det ikke gør: enhver part med adgang til den identifikator kan bygge en adfærdsprofil ud fra den.

Moderne cookiefri analyse løser det samme tælleproblem uden at lagre noget på enheden. Mekanismen er hash-baseret besøgsidentifikation, og den fungerer ved at beregne en kortvarig serversidebaseret identifikator ud fra data, som serveren allerede har.

Hvorfor cookies og localStorage løste det (og skabte juridiske problemer)

Tiltrækningskraften ved cookies og localStorage for analyse var indlysende: de giver dig en stabil identifikator, der overlever på tværs af forespørgsler, på tværs af faner og ofte på tværs af sessioner, uden nogen serverside-tilstand. Browseren udfører alt arbejdet. Du sætter en cookie ved første besøg, du læser den ved enhver efterfølgende forespørgsel, du behøver aldrig at tænke på identitet igen.

Problemet er, at den mekanisme er lovmæssigt reguleret. Artikel 5, stk. 3 i ePrivacy-direktivet behandler "lagring af oplysninger" og "opnåelse af adgang til oplysninger, der allerede er lagret" på brugerens enhed som udløser for samtykke. Cookies er det kanoniske eksempel. Det er localStorage også. Det er sessionStorage også. Det er IndexedDB også. Det er enhver form for enhedsfingerprinting, der læser stabile egenskaber ved hardwaren eller softwaren.

Det betyder, at ethvert analyseværktøj, der er afhængigt af enhedslagring til at tælle unikke, enten har brug for et samtykkebanner eller skal kvalificere sig til en af de snævre undtagelser — hvilket for analyse typisk kræver strengt førsteparts brug, ingen cross-site tracking, begrænset opbevaring og en tilsynsmyndighed, der er villig til at acceptere konfigurationen. Overholdelsesrummet er snævert, og konsekvenserne af at tage fejl har været alvorlige. Franske, tyske og østrigske databeskyttelsesmyndigheder har alle udstedt påbud mod websites, der kører Google Analytics i standardkonfigurationen.

Den hash-baserede tilgang omgår dette fuldstændigt ved at flytte identifikatoren væk fra enheden.

Det hash-baserede alternativ

Grundidéen er enkel: i stedet for at lagre en identifikator på enheden og sende den tilbage til serveren ved hver forespørgsel, beregner serveren en identifikator fra bunden ved hver forespørgsel ved hjælp af attributter, som HTTP-protokollen allerede bærer. Browseren er aldrig involveret. Intet lagres. Intet læses.

For at dette kan fungere som en besøgstæller, skal den beregnede identifikator være:

  • Stabil i den tidsperiode, du vil tælle (typisk en dag)
  • Uforudsigelig for alle uden adgang til serversidehemmeligheden
  • Ikke-sammenkoblelig på tværs af tidsperioder eller på tværs af sites, så den ikke kan bruges til at bygge en langsigtet profil
  • Irreversibel, så serveren ikke kan (og angribere ikke kan) gendanne de oprindelige input fra den gemte hash

En kryptografisk hash-funktion giver dig alle disse egenskaber, når du fodrer den med de rigtige input og roterer de rigtige komponenter.

Sådan fungerer det

Her er den generelle form af algoritmen brugt af Web-Tracking.eu og lignende cookiefri analyseværktøjer. De præcise detaljer varierer mellem leverandører, men byggestenene er de samme.

function visitorId(request, siteId) {
    const ip     = request.remoteAddr;
    const ua     = request.headers['user-agent'];
    const date   = today('UTC');        // YYYY-MM-DD
    const salt   = dailySalt();         // random bytes, rotated every day

    const input  = ip + '|' + ua + '|' + siteId + '|' + date + '|' + salt;
    const hash   = sha256(input);

    // raw inputs are discarded here, only the hash leaves this function
    return hash;
}

Det er hele mekanismen. Ved hver indkommende forespørgsel til vores tracker-endepunkt gør serveren:

  1. Tager IP-adressen og User-Agent-headeren fra forespørgslen
  2. Tilføjer den aktuelle UTC-dato, site-ID'et og den daglige hemmelige salt
  3. Kører det hele gennem SHA-256
  4. Bruger den resulterende hash som besøgende-ID for den forespørgsel
  5. Kasserer den oprindelige IP, User-Agent og salt — kun hashen lagres

Browseren ser aldrig denne hash. Den skrives ikke til en cookie, returneres ikke i en Set-Cookie-header, lagres ikke i localStorage, ekkoer ikke tilbage i noget svar. Den lever udelukkende i vores database som en kort hex-streng, der identificerer "den besøgende, der sendte disse forespørgsler på denne dag."

Hvorfor daglig rotation er vigtig

Datokomponenten i inputtet er det enkelt vigtigste stykke privatlivsteknik i denne ordning. Uden den ville hver forespørgsel fra den samme (IP, User-Agent, site)-triplet producere den samme hash for evigt. Hashen ville reelt være en vedvarende, global identifikator — præcis det, vi forsøger at undgå.

Med daglig rotation ændres hashen for en given besøgende ved midnat UTC hver dag. En besøgende, der kommer tilbage i morgen, producerer en helt anden hash, som ikke kan skelnes fra en splinterny besøgende. Vi kan ikke forbinde deres mandag-besøg med deres tirsdag-besøg, fordi vi ikke har nogen mekanisme til at bygge bro mellem de to hashes.

Dette ofrer noget analytisk styrke. Vi kan ikke beregne en 7-dages unik besøgstælling ved at tælle distinkte hashes; vi må estimere den ud fra daglige tællinger og en antagelse om tilbagevendelsesrate, eller præsentere daglige unikke og lade operatøren fortolke dem. Afvejningen er bevidst: vi får lov at måle publikum uden at bygge en sporings-infrastruktur.

Nogle leverandører roterer efter en anden tidsplan (ugentligt, månedligt). Vores opfattelse er, at daglig er den rigtige standard. Ugentlig og månedlig rotation giver lidt bedre analyse, men svagere privatlivsgarantier, og enhver databeskyttelsesmyndighed, der udfordrer en cookiefri tilgang, er mere tilbøjelig til at acceptere et kort rotationsvindue.

Hvorfor saltet betyder noget

Den daglige hemmelige salt gør to ting. For det første forhindrer det rainbow-table-angreb: uden saltet kunne en angriber, der fik fat i en liste over vores hashes, forudberegne hashes for almindelige (IP, User-Agent)-kombinationer og gendanne input. Med en hemmelig salt, som vi aldrig videregiver, er hashrummet effektivt randomiseret, og forudberegning er ubrugelig.

For det andet betyder saltet, at selv hvis den præcise algoritme og hele inputstrukturen blev offentliggjort (som de er i dette indlæg), kan ingen uden for vores servere beregne besøgende-ID'et for en kendt (IP, User-Agent)-kombination. Du skal bruge saltet, og saltet roteres dagligt og forlader aldrig serveren.

Saltet er langt (32 bytes kryptografisk tilfældige data), lagret i en secret manager adskilt fra analysedatabasen og roteret hver 24. time. Gamle salte slettes efter rotationen, så selv en fuld databasedump ville ikke lade dig rekonstruere gårsdagens salte for at beregne gårsdagens hashes.

Hvilke data hashes

Ingredienserne i vores hash er bevidst minimale:

  • IP-adresse — identificerer forespørgslens netværksoprindelse. Inde i hashen, aldrig lagret rå.
  • User-Agent — identificerer browseren og OS i brede træk. Inde i hashen, aldrig lagret rå som identifikator.
  • Site-ID — afgrænser hashen til et enkelt website. En besøgende, der dukker op på to sites sporet af Web-Tracking.eu, producerer to urelaterede hashes.
  • Aktuel UTC-dato — roterer identifikatoren dagligt.
  • Hemmelig salt — roterer identifikatoren dagligt og forhindrer reverse engineering.

Vi hasher ikke nogen enhedsegenskaber ind, der ville kræve læsning fra browseren (skærmstørrelse, sprog, plugins, fonte, canvas-rendering osv.). Hvad browseren sender frivilligt i HTTP-headere, er fair game; hvad der ville kræve en JavaScript-læsning fra enheden, er det ikke.

Dette er en vigtig linje. Det betyder, at vores "fingeraftryk" kun er så stabilt som IP-adressen og User-Agent. En besøgende, der skifter netværk midt på dagen, får en ny hash. En besøgende, der opdaterer sin browser, får en ny hash efter opdateringen. En besøgende, der bruger en VPN, der roterer exit-IP'er, får en ny hash ved hver rotation. Vi accepterer denne upræcisionen som prisen for ikke at bygge et rigtigt fingeraftryk.

Hvorfor dette ikke identificerer brugere

Hash-outputtet er en 64-tegns hex-streng, der ser sådan ud:

a3f2c9b4e8d1f7a5c6b9e2d4f8a1c3b5e7d9f2a4c6b8e1d3f5a7c9b2e4d6f8a0

I sig selv kan den streng ikke knyttes til nogen individuel person. Den kan ikke vendes om for at gendanne IP eller User-Agent. Den kan ikke korreleres på tværs af dage, fordi datoen og saltet ændres. Den kan ikke korreleres på tværs af sites, fordi site-ID'et ændres.

De rå input (IP og User-Agent) eksisterer i hukommelsen i de millisekunder, det tager at beregne hashen. De skrives aldrig til disk, kopieres aldrig til logs, sendes aldrig til nogen tredjepart, opbevares aldrig i nogen form. Det eneste, der består, er hashen, og hashen har ingen af de egenskaber, der ville gøre den til persondata under GDPR Artikel 4, stk. 1: den identificerer ikke, den kan ikke udpege, og den kan ikke knyttes til en identificerbar person uden adgang til data, vi ikke har.

Artikel 29-gruppens Opinion 05/2014 om anonymiseringsteknikker opstiller tre tests: udpegning, linkability og slutning. Vores daglige roterende, site-afgrænsede, saltede hash fejler alle tre tests som identifikator af individer, hvilket er præcis pointen.

Begrænsninger: brugere i samme husstand, delte IP'er, VPN'er

Hash-baseret identifikation er ikke en perfekt tæller. Den bytter nøjagtighed for privatliv, og måderne den er ufuldkommen på, er værd at forstå.

Brugere i samme husstand, der deler en IP-adresse og bruger den samme browserversion, vil producere den samme hash. To personer på det samme hjemme-Wi-Fi, begge der bruger Chrome på Windows, begge på det samme site på den samme dag, vil blive talt som én besøgende. Cookie-baseret analyse ville skelne dem (hver får sin egen cookie); hash-baseret analyse vil ikke.

Virksomhedsnetværk bag en NAT kan kollapse mange reelle besøgende til en enkelt hash. Et kontor med 200 personer, der tilgår dit site fra den samme offentlige IP, alle der kører den samme IT-udrullede browserbuild, vil se ud som én besøgende. Cookie-baseret analyse ville skelne dem; hash-baseret analyse vil ikke.

VPN- og Tor-brugere har det modsatte problem: en enkelt person, hvis exit-IP roterer, vil producere flere hashes og blive talt flere gange. Cookie-baseret analyse ville se dem som én besøgende; hash-baseret analyse vil overtælle.

Brugere på flere enheder vil altid blive talt separat, fordi IP + User-Agent-kombinationen er forskellig. Dette er den samme begrænsning som cookie-baseret analyse uden sammenkobling af identitet på tværs af enheder.

Nettoeffekten er, at cookiefri analyse har tendens til at undertælle unikke i tætte, delte miljøer og overtælle unikke for privatlivsbevidste brugere med roterende IP'er. Begge effekter udjævnes i aggregatet for de fleste websites, men hvis dit publikum er koncentreret i virksomhedsnetværk eller hælder kraftigt mod VPN-brugere, kan tallene afvige fra cookie-baserede tællinger med flere procent i begge retninger.

Vi mener, dette er en acceptabel afvejning, og det gør de fleste af vores kunder også. Analyse er ikke folketælling. Det der betyder noget er kurvens form, sammenligningen mellem dage, effekten af en kampagne, rangeringen af sider. Alle disse bevares perfekt af hash-baseret tælling.

Sammenligning med andre cookiefri tilgange

Flere analyseleverandører er endt på variationer af den samme grundlæggende arkitektur.

  • Plausible brugte historisk en per-site, daglig roterende hash af IP + User-Agent + site + salt. Deres nuværende implementering er meget tæt på det, der er beskrevet ovenfor.
  • Fathom bruger en lignende hash-baseret tilgang med serversideberegning og ingen klient-sidelagring.
  • Pirsch bruger et dagligt roterende fingeraftryk baseret på saltet IP + User-Agent.
  • Simple Analytics beregner en hash af IP + User-Agent + hostname + roterende salt, også dagligt.

Forskellene er hovedsageligt i:

  • Rotationsfrekvens (daglig er typisk, men ikke universel)
  • Om saltet deles på tværs af kunder eller er per-site
  • Hvilke præcise header-felter der inkluderes i hash-inputtet
  • Om IP-adresser trunkeres (v4: sidste oktet, v6: sidste 80 bit) før hashing for yderligere privatliv
  • Hvor længe den resulterende hash opbevares i aggregeret form

Det bemærkelsesværdige er konvergensen. For fem år siden var privatlivs-først-analyse et rodet område med mange konkurrerende arkitekturer. I dag bruger de seriøse spillere alle serverside-hashing med en eller anden form for rotation, fordi det er den eneste arkitektur, der rent undgår ePrivacy-udløseren uden at gå på kompromis med den centrale analytiske opgave.

Bundlinjen

Hash-baseret besøgsidentifikation er ikke et hack eller en omvej. Det er en principfast løsning på et reelt problem: at tælle unikke besøgende uden at lagre noget på deres enheder og uden at bevare rå identifikatorer på serveren. Udført ordentligt, med daglig rotation, en roterende hemmelig salt og kasserede rå input, giver den dig brugbar analyse med stærke privatlivsegenskaber og intet ePrivacy-samtykkekrav.

Udført dårligt — med lange rotationsvinduer, delte salte, opbevarede IP'er eller yderligere enhedsfingerprinting — degraderer den til blot endnu en sporingsordning. Djævelen er i de tekniske detaljer, hvilket er grunden til, at det er værd at forstå, hvad din analyseleverandør faktisk gør under motorhjelmen.


Web-Tracking.eu er en cookiefri analyseplatform. Læs mere om vores tilgang i den juridiske gennemgang intet cookie-banner.