Alle Artikel

HMAC: wie sich ein Hash mit Schlüssel von einem gewöhnlichen Hash unterscheidet

GitHub signiert jeden Webhook mit HMAC-SHA256 im Header X-Hub-Signature-256 — ein Muster, das in der deutschen Entwickler-Community, wo GitHub Actions und Self-Hosted-Runner weit verbreitet sind, praktisch täglich implementiert wird. Der empfangende Server berechnet die HMAC-Signatur aus dem rohen Request-Body und dem gemeinsamen Geheimnis neu und vergleicht sie mit dem Header-Wert. Stimmen sie nicht überein, stammt die Anfrage nicht wirklich von GitHub.

Warum ein geheimer Schlüssel nötig ist, nicht nur ein Hash

Ein gewöhnlicher Hash wie SHA-256 beweist nur, dass Daten unterwegs nicht verändert wurden — nicht, wer sie gesendet hat. Würde ein Server einfach den Webhook-Body hashen und mit einem im Request enthaltenen Hash vergleichen, könnte ein Angreifer eine eigene gefälschte Payload samt passendem Hash erstellen. HMAC löst das, indem es einen geheimen Schlüssel einmischt, den nur Sender und Empfänger kennen: ohne ihn ist eine gültige Signatur praktisch nicht erzeugbar, selbst wenn der Angreifer genau weiß, welche Hash-Funktion verwendet wird.

Warum es nicht einfach "Hash aus Schlüssel plus Nachricht" ist

Das naive Aneinanderhängen von Schlüssel und Nachricht vor dem Hashing (z. B. hash(schlüssel + nachricht)) ist bei manchen Hash-Funktionen anfällig für Length-Extension-Angriffe — ein Angreifer kann teils Daten anhängen und einen neuen gültigen Hash berechnen, ohne den vollständigen Schlüssel zu kennen. HMAC verwendet eine spezielle Konstruktion mit doppeltem Hashing und innerem/äußerem Padding, die diese gesamte Angriffsklasse ausschließt.

Wo HMAC sonst noch vorkommt

Neben der Webhook-Signierung authentifiziert HMAC API-Anfragen und bildet den Kern des TOTP-Algorithmus — jenes Verfahrens, das die sechsstelligen Codes in Authenticator-Apps erzeugt.

Wofür man das braucht

  • Die Echtheit von Webhooks von Zahlungsdienstleistern oder anderen Drittanbietern überprüfen.
  • API-Anfragen signieren, ohne den geheimen Schlüssel selbst über das Netzwerk zu senden.
  • Die interne Funktionsweise von TOTP-Codes und Session-Tokens verstehen.

Vergleich in konstanter Zeit

Eine erhaltene Signatur mit dem gewöhnlichen Operator === zu vergleichen, ist unsicher: Ein solcher Operator bricht meist beim ersten abweichenden Byte ab, und die Ausführungszeit verrät einem Angreifer, wie viele führende Bytes er richtig erraten hat. Ein sauber implementierter Webhook-Handler verwendet immer eine Vergleichsfunktion in konstanter Zeit — etwa hash_equals in PHP oder crypto.timingSafeEqual in Node.js —, die stets alle Bytes prüft, unabhängig davon, wo die erste Abweichung liegt.

Tool ausprobieren