Een fatsoenlijke site kent je wachtwoord niet. Niet omdat hij niet wil: hij kan het niet.
Dat klinkt als een goocheltruc, want elke keer dat je het intikt laat het systeem je binnen, en om je binnen te laten moet het iets controleren. Maar controleren is niet weten. De server bewaart een afdruk die uit je wachtwoord is berekend; als je het intikt, berekent hij de afdruk opnieuw en vergelijkt. Komen ze overeen, dan mag je erdoor. Nergens in dat proces hoeft het wachtwoord zelf ergens te staan.
Daaruit volgt het duidelijkste teken om een serieuze dienst van een onserieuze te onderscheiden: sturen ze je het wachtwoord per mail op als je het vergeten bent, dan hadden ze het bewaard. En wat bewaard wordt, belandt vroeg of laat bij iemand anders.
1979 het idee om ze niet te bewaren — en om het traag te doen
In 1979 publiceerden Robert Morris en Ken Thompson in Communications of the ACM ‘Password Security: A Case History’, waarin ze vertelden wat ze in Unix hadden gedaan. Het is een verslag van opgedane lessen, en er liggen twee ideeën in vast die we vandaag vanzelfsprekend vinden.
Het eerste hebben ze niet uitgevonden — de hash bewaren in plaats van het wachtwoord gebeurde al eerder — maar ze legden het beter uit dan wie ook: niet het wachtwoord bewaren, maar de hash ervan. Een functie die je wachtwoord omzet in een willekeurig ogende waarde en die je niet kunt teruglopen: van de hash kom je niet terug bij het wachtwoord.
Het tweede is wel van hen: de salt. Een willekeurige waarde die voor iedere gebruiker anders is en die vóór het hashen door het wachtwoord wordt gemengd. Zonder salt hebben twee mensen met hetzelfde wachtwoord dezelfde hash — het gestolen bestand verandert in een spelletje dubbelen zoeken — en, erger, kan iemand één keer een gigantische tabel vooraf berekenen en die tegen alle databases ter wereld inzetten. De salt maakt je wachtwoord niet moeilijker te raden: hij zorgt dat het raden voor niemand anders bruikbaar is.
Maar in datzelfde artikel staat een derde idee, veel minder vaak geciteerd, en dat is het idee waar het hier om draait: ze maakten de functie met opzet traag. Niet uit slordigheid. Expres. Een wachtwoord versleutelen kostte veel meer dan technisch nodig was, want wie één keer per ochtend inlogt merkt daar niets van, en wie miljoenen kandidaten uitprobeert wel.
Daar staat de hele kwestie, in één zin van bijna vijftig jaar oud.
Waarom traagheid de enige eerlijke verdediging is
Bijna alle verdedigingen in de informatica zijn asymmetrisch: ze kosten de verdediger weinig en de aanvaller veel. Versleutelen is goedkoop; ontsleutelen zonder de sleutel is onhaalbaar. De verdediger speelt met structureel voordeel.
Bij het opslaan van wachtwoorden niet. Hier voeren verdediger en aanvaller precies dezelfde functie uit. Jij berekent de hash om te controleren of je het goed hebt; hij berekent hem om te controleren of hij het goed heeft. Het is de enige race in de beveiliging waarin allebei op dezelfde benen lopen.
Als je niet harder kunt lopen dan je tegenstander, blijft er één zet over: de baan voor allebei duurder maken. Jij betaalt die prijs één keer per keer inloggen. Hij één keer per poging. Omdat hij ordes van grootte meer pogingen nodig heeft dan jij, pakt dezelfde rekening voor jullie onvergelijkbaar uit. Dat is precies wat een wachtwoordhash doet.
Daarom zijn snelle functies die voor andere dingen uitstekend zijn — SHA-256, bijvoorbeeld — hier een beroerde keuze. Ze zijn snel. En snel is nu net wat we niet willen.
1999 bcrypt, en de kosten als draaiknop
Het probleem met een trage functie is dat hardware niet stilzit. Wat in 1979 traag was, is later onmiddellijk. Een verdediging die op de computers van één decennium is afgesteld, veroudert vanzelf, zonder dat iemand haar aanraakt.
In 1999 presenteerden Niels Provos en David Mazières bcrypt op de USENIX Annual Technical Conference, met een titel die alles al zegt: A Future-Adaptable Password Scheme.
Het idee: de kosten zitten niet in de functie, maar in een parameter. bcrypt heeft een kostenfactor die jij bepaalt en die naast de hash wordt bewaard. Wordt hardware veel sneller, dan draai je het getal omhoog en kosten nieuwe wachtwoorden weer wat ze horen te kosten, zonder van algoritme te wisselen.
Het is een ontwerp dat uitgaat van zijn eigen veroudering en zich daarop voorbereidt. Er is bitter weinig software die dat doet.
2009 scrypt, en de ontdekking dat tijd niet genoeg is
bcrypt maakt rekentijd duur, en dat werkte. Tot de aanvaller ophield met hetzelfde soort machine te werken als de verdediger.
Een server heeft een handjevol snelle, algemene kernen. Een GPU heeft een absurd aantal kleine kernen die allemaal hetzelfde parallel doen, en een ASIC gaat nog verder: silicium gebakken om één enkele bewerking uit te voeren. Als je verdediging neerkomt op ‘deze bewerking kost X’, dan kan iemand hardware bouwen die heel veel keer X tegelijk doet. De verdediger zit nog steeds met zijn server.
In 2009 presenteerde Colin Percival scrypt met een ander argument: Stronger Key Derivation via Sequential Memory-Hard Functions. Zitten de kosten alleen in het rekenwerk, dan laat het zich parallelliseren. Maar geheugen krijg je niet cadeau. Dwing de functie veel RAM te gebruiken en die zo te doorlopen dat je er niet omheen kunt, en opeens kan de aanvaller geen kernen meer bijstapelen: elke kern zou zijn eigen geheugen nodig hebben. En de kernen van een GPU hebben veel rekenkracht en per stuk bijzonder weinig RAM.
Percival maakte niet de bewerking duurder. Hij maakte de hardware duurder die je nodig hebt om haar massaal te herhalen. Dat is een niveauverschil: je valt het budget van de aanvaller aan, niet zijn klok.
2015 Argon2, en het einde van de discussie
Dat er meerdere redelijke opties bestonden hielp niemand bij het kiezen. Dus deed de cryptografische gemeenschap wat ze meestal doet als ze iets wil beslechten: een openbare wedstrijd. De Password Hashing Competition ontving kandidaten, onderwierp ze jarenlang aan openbare analyse en riep in 2015 Argon2 uit tot winnaar.
Argon2 erft beide lessen: kosten in tijd en kosten in geheugen, allebei apart in te stellen, plus het aantal threads. Het is geen magie. Het is de nette synthese van 1979, 1999 en 2009, nagekeken door mensen wier werk bestond uit pogingen om haar te breken.
Wat dit voor jou betekent
Bijna niets hiervan ligt in jouw handen, en dat mag gezegd worden: de hash kiest de site, niet jij. Je kunt het beste wachtwoord ter wereld hebben en het alsnog platgeslagen in een Excel-bestand zien belanden.
Maar de andere kant van de vergelijking hangt wél van jou af. Dit hele bouwwerk — de salt, de kosten, het geheugen — dient om elke poging van de aanvaller duurder te maken. Wat bepaalt hoeveel pogingen hij nodig heeft, is jouw wachtwoord. Staat het in een woordenboek, dan redt geen enkele trage functie je: het valt bij de eersten. Is het lang en lijkt het nergens op, dan wordt die prijs per poging vermenigvuldigd met een aantal pogingen dat niet in de beschikbare tijd past.
Daarom meet onze generator entropiebits en geen percentages, en daarom zoekt de checker je wachtwoord eerst op in woordenboeken voordat hij symbolen gaat tellen. Zij zetten de prijs per poging; jij zet het aantal pogingen. Geen van beide helften werkt zonder de andere.
En ja: het blijft dezelfde vraag als altijd. Alleen probeert iemand aan de andere kant hem nu vele malen per seconde te beantwoorden, en zijn we sinds 1979 bezig om elke van die keren geld te laten kosten.
Bronnen: R. Morris en K. Thompson, ‘Password Security: A Case History’, Communications of the ACM, 1979 · N. Provos en D. Mazières, ‘A Future-Adaptable Password Scheme’, USENIX Annual Technical Conference, 1999 (bcrypt) · C. Percival, ‘Stronger Key Derivation via Sequential Memory-Hard Functions’, 2009 (scrypt) · Password Hashing Competition, winnaar Argon2, 2015.