SHA-1-hash maken

Plak een tekst en lees de SHA-1 ervan: veertig hexadecimale tekens, berekend uit de UTF-8-bytes. SHA-1 is voor handtekeningen en certificaten gebroken — in 2017 werd een botsing aangetoond en de kosten zijn sindsdien alleen gedaald — en de reden dat deze pagina bestaat is dat er nog systemen zijn die er nu eenmaal om vragen. Het rekenen gebeurt in je browser.

Resultaat

Het antwoord verschijnt hier terwijl je typt.

  • Waar het draait

    Er wordt niets geüpload, want er is geen bestand — het wordt in deze pagina uitgerekend.

  • Geen wachtrij, geen account

    Het antwoordt zo snel als je machine kan, en vraagt nooit wie je bent.

  • Zo vaak als je wilt

    Er wordt niets geteld en niets begrensd — nog eens antwoorden kost ons niets.

Hoe het werkt

  1. Plak de tekst in het veld.
  2. Kopieer de 40 hexadecimale tekens.
  3. Er is niets geüpload.

Wat er in 2017 precies brak

In februari 2017 lieten onderzoekers van Google en het CWI in Amsterdam twee verschillende PDF-bestanden zien met dezelfde SHA-1. Dat heet een botsing, en het kostte destijds ongeveer 6.500 CPU-jaren en 110 GPU-jaren — veel, en betaalbaar voor wie het echt wil.

In 2020 kwam de volgende stap: een botsing met gekozen voorvoegsel, waarmee de aanvaller allebei de begindelen zelf mag bepalen. Dat maakt de aanval bruikbaar tegen echte formaten, en de geschatte kosten waren toen enkele tienduizenden euro’s aan gehuurde rekentijd. Sindsdien is die prijs alleen verder gezakt.

Waarom Git het nog gebruikt

Git identificeert elk object met zijn SHA-1, en dat is er niet uit te halen zonder de geschiedenis van elke repository ter wereld te herschrijven. Het weerwoord is dat Git de hash gebruikt om objecten te benoemen en niet om te bewijzen wie ze heeft gemaakt; daarvoor zijn de ondertekende commits en tags met GPG.

Werkeloos is men niet gebleven. Sinds 2017 draait er in Git een botsingsdetectie die de bekende aanvalspatronen herkent en zulke objecten weigert, en er is een overgang naar SHA-256 gespecificeerd die in delen wordt uitgerold. Het is dus geen ontkenning maar een migratie van een formaat waar zeer veel op steunt.

Een gebroken schema lap je niet op

Een terugkerend idee is om SHA-1 twee keer toe te passen, of er een salt bij te doen, en zo het probleem te omzeilen. Dat werkt niet: de zwakte zit in de interne constructie, en die verdwijnt niet door de uitvoer nog eens door dezelfde functie te halen.

Wat wel iets oplost is een andere functie. Waar de keuze vrij is, is dat SHA-256; waar een sleutel in het spel hoort, is dat HMAC of een echte digitale handtekening. Zelfbedachte lagen om een gebroken primitief heen leveren iets op dat nergens is onderzocht, en dat is doorgaans slechter dan het origineel.

De korte vorm, en wanneer die botst

Git toont standaard de eerste zeven tekens van een object-id, wat achtentwintig bits is en dus zo’n 268 miljoen mogelijkheden. Dat lijkt veel en het is het niet: bij enkele tienduizenden objecten wordt een toevallige botsing waarschijnlijk, en Git lengt de weergave dan zelf uit.

Het is een goed voorbeeld van het verjaardagsprobleem in het klein. Wie zelf op een afgekorte hash vertrouwt — in een uitroltag, in een bestandsnaam, in een cachesleutel — moet uitrekenen hoeveel waarden er in omloop komen, want de grens ligt veel lager dan het aantal tekens suggereert.

Veertig tekens

Een SHA-1 is 160 bits, geschreven als veertig hexadecimale tekens. Vast van lengte, ongeacht de invoer, net als bij de andere hashfuncties.

Veertig tekens is daarmee zelf een aanwijzing. Kom je een waarde van veertig hextekens tegen in een logbestand, in een databaseveld of in een API-antwoord, dan is het bijna altijd een SHA-1 — vaak een Git-object-id, soms een oude sessiesleutel, soms een vingerafdruk van een certificaat uit de tijd dat die nog in SHA-1 werden afgedrukt.

Het object-id van Git is niet de hash van het bestand

Wie de SHA-1 van een bestand berekent en die naast het object-id van Git legt, ziet twee verschillende waarden en denkt dat er iets stuk is. Er is niets stuk: Git hasht niet het bestand maar een kop plus de inhoud, namelijk `blob `, het aantal bytes, een nulbyte en dan pas de inhoud.

Die kop zit erbij zodat de typen objecten — blob, tree, commit, tag — niet met elkaar kunnen botsen. Het gevolg is dat je een object-id niet met een gewone bestandshash kunt reproduceren, en dat `git hash-object` het gereedschap is dat je daarvoor nodig hebt.

Het regeleinde, opnieuw

Net als bij de andere hashfuncties is de meest voorkomende oorzaak van een verschil één byte aan het eind. `echo tekst | sha1sum` hasht de tekst met het regeleinde dat `echo` toevoegt; `echo -n` haalt dat weg.

Bij Git komt daar nog iets bovenop: de instelling `core.autocrlf` kan regeleindes bij het inchecken en uitchecken herschrijven, zodat hetzelfde bestand op Windows en op Linux verschillende bytes heeft. Dan verschilt niet alleen de SHA-1 van het bestand maar ook het object-id, en dat is geen fout maar een instelling.

Wanneer je het wel en niet gebruikt

Niet gebruiken: voor certificaten, voor handtekeningen, voor het controleren van downloads waar een tegenstander in het spel kan zijn, en voor alles wat nieuw gebouwd wordt. Browsers vertrouwen sinds 2017 geen SHA-1-certificaten meer, en dat is de status die hier telt.

Wel te verantwoorden: waar iets anders erom vraagt en je het niet kunt veranderen — een Git-object nabouwen, een oude koppeling voeden, een waarde uit een bestaand systeem controleren. Dat is de reden dat deze pagina bestaat, en het is ook de enige reden.

HMAC-SHA1 is een ander verhaal

Verwarrend genoeg geldt HMAC-SHA1 nog altijd als aanvaardbaar, ook al is SHA-1 zelf gebroken. Het komt doordat HMAC niet op botsingsbestendigheid leunt maar op een zwakkere eigenschap, en die is bij SHA-1 niet aangetast. Daarom staat het nog in bestaande protocollen zonder dat dat een fout is.

Dat betekent niet dat je het opnieuw zou kiezen. Nieuwe systemen nemen HMAC-SHA256, alleen al omdat het uitleggen van het onderscheid duurder is dan het verschil. Maar wie HMAC-SHA1 in een bestaande koppeling aantreft, hoeft dat niet als acuut lek te behandelen.

Waar het nog verplicht opduikt

Naast Git zit SHA-1 in de vingerafdrukken van SSH-sleutels in oudere weergaven, in de handtekeningen van OAuth 1.0, in sommige SAML-koppelingen en in de WebSocket-handdruk, waar de server een vaste tekst achter de sleutel plakt en er de SHA-1 van teruggeeft.

In dat laatste geval is er geen veiligheidsclaim aan verbonden: het is een bewijs dat de server het protocol begrijpt en niet dat er iets geheim is. Zulke gevallen zijn de reden dat SHA-1 nog decennia in specificaties zal staan zonder dat er iemand mee wil beveiligen.

De AVG-regel die hier geldt

Een hash van een persoonsgegeven blijft onder de AVG een persoonsgegeven zolang herleiding mogelijk is, en bij SHA-1 is dat niet anders dan bij MD5 of SHA-256. Het algoritme verandert niets aan die kwalificatie; de omvang en voorspelbaarheid van de verzameling wel.

Wat deze pagina wel regelt is dat de tekst die je hier plakt op je eigen machine wordt gehasht en niet aan ons verstrekt. Bij een waarde uit een bestaand systeem — een sessiesleutel, een klantnummer, een oude token — is dat het punt waarop het verschil te maken valt.

SHA-1-hash maken: veelgestelde vragen

Mag ik SHA-1 nog gebruiken?

Alleen waar iets anders erom vraagt en je het niet kunt veranderen. Voor certificaten, handtekeningen en nieuwe systemen niet: er is sinds 2017 een aangetoonde botsing en de kosten zijn sindsdien gedaald.

Als het gebroken is, waarom gebruikt Git het dan?

Omdat de object-id’s van elke repository ter wereld eraan vastzitten. Git gebruikt de hash om te benoemen, niet om te bewijzen wie iets maakte, draait sinds 2017 botsingsdetectie en migreert in stappen naar SHA-256.

Helpt het om SHA-1 twee keer of met een salt toe te passen?

Nee. De zwakte zit in de interne constructie en verdwijnt niet door de uitvoer opnieuw door dezelfde functie te halen. Waar de keuze vrij is, hoort SHA-256 te staan.

Waarom komt het niet overeen met het object-id van mijn commit?

Omdat Git niet het bestand hasht maar de tekst blob, het aantal bytes, een nulbyte en dan pas de inhoud. Dat kun je niet met een gewone bestandshash nabouwen; daarvoor is git hash-object.

Verlaat de tekst mijn machine?

Nee. Het rekenen gebeurt op deze pagina. Dat telt, want wie SHA-1 nodig heeft, werkt meestal met waarden uit een bestaand systeem: sessiesleutels, oude tokens, object-id’s.

Andere hulpmiddelen