HMAC-Generator
Berechnet HMAC-SHA-1, SHA-256, SHA-384 und SHA-512 aus Nachricht und Schlüssel und erkennt, von welchem eine gegebene Signatur stammt.
Geben Sie einen Schlüssel ein, um die Signaturen zu berechnen.
Was dieses Werkzeug tut
HMAC macht aus einer Nachricht und einem gemeinsamen Geheimnis eine kurze Signatur. Wer dasselbe Geheimnis hat, kann sie nachrechnen und sehen, ob die Nachricht unverändert ankam und von jemandem stammt, der das Geheimnis ebenfalls kennt. Dieses Werkzeug berechnet alle vier gängigen Varianten auf einmal und sagt Ihnen zu einer zugesandten Signatur, welche davon sie erzeugt hat.
Diese zweite Richtung ist meist der Grund, weshalb man hier landet. Ein Webhook scheitert an der Prüfung, und die eigentliche Frage lautet nicht „ist diese Signatur gültig“, sondern „welche der mehreren plausiblen Sachen mache ich anders als der Absender“. Ein Präfix wie sha256= vor einer eingefügten Signatur wird erkannt und entfernt, sodass ein Header-Wert genau so eingefügt werden kann, wie er angekommen ist.
Am Schlüssel geht es schief
HMAC signiert Bytes mit Bytes. Die Nachricht liegt meist auf der Hand — der rohe Anfragerumpf —, der Schlüssel fast nie, denn ein Geheimnis kommt als Zeichenkette an, und eine Zeichenkette ist erst dann Bytes, wenn Sie entschieden haben, wie sie zu lesen ist:
a3f2 -> 61 33 66 32 4 bytes als Text a3f2 -> a3 f2 2 bytes als Hex
Beide Lesarten sind legitim, beide ergeben eine völlig wohlgeformte Signatur, und die beiden Signaturen haben nichts gemeinsam. Nichts warnt Sie: kein Fehler, keine Beschwerde über die Länge, nur ein Wert, der nicht zu dem passt, den der Absender berechnet hat. Deshalb ist die Schlüsselkodierung hier eine sichtbare Wahl statt einer Vermutung — wenn eine Signatur nicht passt, ist das das Erste, was man umschaltet.
Als grobe Orientierung: ein Geheimnis mit einem Präfix wie whsec_ oder eine Folge aus Groß- und Kleinbuchstaben und Ziffern ist normalerweise als Text gemeint; eine Zeichenkette aus genau 32 oder 64 Zeichen, die nur 0-9 und a-f verwendet, ist meist Hex; und eine, die auf = endet, ist fast sicher Base64. Prüfen Sie aber die Dokumentation des Absenders statt der Form, denn die Form ist kein Beweis.
Die Nachricht muss genau die richtigen Bytes sein
Die andere Hälfte einer Abweichung ist die Nachricht. HMAC ist über Bytes definiert, also ändert alles, was die Bytes ändert, die Signatur vollständig — es gibt keine Teilpunkte und kein Beinahe.
- JSON neu serialisieren. Einen Rumpf zu parsen und wieder auszugeben kann Schlüssel umsortieren, Leerzeichen ändern oder Zahlen normalisieren. Signieren und prüfen Sie den rohen Rumpf, den Sie erhalten haben, nie eine hin- und zurückgewandelte Kopie.
- Ein abschließender Zeilenumbruch. Manche Werkzeuge fügen einen hinzu, wenn man den Rumpf in eine Datei speichert; er ist ein Byte, und er ändert alles.
- Die Zeichenkodierung. Ein Rumpf mit Nicht-ASCII-Text muss auf beiden Seiten in derselben Kodierung gelesen werden — in der Praxis UTF-8.
- Kompression oder Middleware. Wenn etwas vor Ihrem Handler den Rumpf entpackt oder umschreibt, prüfen Sie davor, nicht danach.
Viele Anbieter signieren zudem nicht den Rumpf allein. Stripe signiert einen Zeitstempel und den Rumpf, verbunden durch einen Punkt; AWS signiert eine kanonische Anfrage aus Methode, Pfad, Headern und einem Hash der Nutzlast. Scheitert die Prüfung gegen den blanken Rumpf, ist die signierte Zeichenkette vermutlich nicht der blanke Rumpf — das steht in der Dokumentation des Absenders und lohnt sich, bevor man weiter sucht.
Warum SHA-1 hier angeboten wird und im Hash-Werkzeug nicht
Das Hash-Werkzeug markiert SHA-1 als gebrochen. Dieses führt HMAC-SHA-1 ohne Warnung, und das ist Absicht, kein Versehen.
Für Signaturen und Zertifikate ist SHA-1 unbrauchbar, weil sich Kollisionen konstruieren lassen: Man kann zwei verschiedene Dokumente dazu bringen, denselben Digest zu haben. HMAC hängt nicht von dieser Eigenschaft ab. Seine Sicherheit ruht auf dem geheimen Schlüssel, und die Konstruktion — die Nachricht zweimal zu hashen, den Schlüssel beide Male eingemischt — hält auch dann, wenn der zugrunde liegende Hash kollisionsschwach ist. HMAC-SHA-1 bleibt solide und ist das, was OAuth 1.0a und ältere AWS-Signierung verwenden; ein Werkzeug, das die Berechnung verweigerte, wäre also schlicht weniger nützlich, ohne sicherer zu sein.
Für Neues ist SHA-256 die vernünftige Wahl. Längere Digests sind hier nicht nennenswert stärker — die Sicherheitsgrenze ist der Schlüssel, nicht die Digest-Länge —, also lohnen SHA-384 und SHA-512 nur, wenn etwas, mit dem Sie zusammenarbeiten müssen, sie verlangt.
Signaturen sicher vergleichen
Diese Seite vergleicht mit einem gewöhnlichen Zeichenkettenvergleich, und das ist hier in Ordnung: Sie halten den Schlüssel selbst, es gibt nichts zu verraten. In einem Server, der eine eingehende Anfrage prüft, ist es nicht in Ordnung. Ein gewöhnlicher Vergleich hält beim ersten abweichenden Byte an, sodass die benötigte Zeit verrät, wie viel einer Rateversion stimmte, und wer viele Anfragen senden kann, kann eine gültige Signatur Byte für Byte rekonstruieren.
Nehmen Sie den Vergleich in konstanter Zeit, den Ihre Plattform bietet — crypto.timingSafeEqual in Node, hmac.compare_digest in Python, hash_equals in PHP — auf den rohen Bytes statt auf Hex-Zeichenketten. Dazu: vergleichen Sie gegen eine selbst berechnete Signatur, statt einem in der Anfrage genannten Algorithmus zu vertrauen, und weisen Sie eine Nachricht zurück, deren Zeitstempel weit von jetzt entfernt ist, damit eine alte gültige Signatur nicht wiedereingespielt werden kann.
HMAC ist weder ein Hash noch eine Signatur
Hier werden drei Dinge verwechselt, und der Unterschied zählt für das, was man hinterher behaupten kann:
- Ein Hash nimmt eine Nachricht und liefert einen Digest. Jeder kann ihn berechnen, er belegt also, dass sich die Nachricht nicht versehentlich geändert hat — nicht, dass sie von jemand Bestimmtem kommt.
- Ein HMAC nimmt eine Nachricht und ein gemeinsames Geheimnis. Beide Seiten haben denselben Schlüssel, er belegt also, dass der Absender das Geheimnis kannte. Welche Seite gesendet hat, kann er nicht belegen, denn beide hätten ihn erzeugen können.
- Eine Signatur nutzt einen privaten Schlüssel, den nur der Absender hat, und einen öffentlichen, mit dem jeder prüfen kann. Das ergibt die Nichtabstreitbarkeit: Der Absender kann sie später nicht leugnen.
HMAC ist damit das richtige Werkzeug zwischen zwei Systemen, die bereits ein Geheimnis teilen — Webhooks, interne APIs, Sitzungstoken — und das falsche, wenn man einem Dritten beweisen muss, wer etwas gesendet hat. Beachten Sie außerdem: Es authentifiziert, verbirgt aber nichts. Die Nachricht reist im Klartext, und HMAC sagt nichts über Vertraulichkeit.
Eine Stripe-Webhook-Signatur prüfen
Stripe ist hier das einzige Rezept, das kein Einfügen ist, und meist das, mit dem man es schon versucht hat, bevor man hier landet. Der Header Stripe-Signature ist eine kommagetrennte Liste von Elementen und keine Signatur, und die Zeichenkette, die Stripe signiert hat, ist nicht der Anfragerumpf allein. Stripes eigene Dokumentation bricht den Header der Lesbarkeit halber in Zeilen um; ein echter kommt in einer einzigen Zeile an.
Stripe-Signature: t=1492774577, v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd, v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
- Nachricht: der Wert von t=, dann ein Punkt, dann der rohe Anfragerumpf genau so, wie er ankam. Für den Header oben beginnt diese Zeichenkette mit 1492774577. und der Rumpf folgt unmittelbar. Stripe nennt sie die signierte Nutzlast, und sie ist der ganze Grund, weshalb eine Stripe-Signatur nie zum Rumpf allein passt.
- Schlüssel: das Signaturgeheimnis genau dieses einen Endpunkts, vollständig, samt seinem Präfix whsec_. Es ist nicht Ihr API-Schlüssel und nicht das Geheimnis eines anderen Endpunkts — dieselbe URL zweimal registriert hat zwei davon.
- Schlüsselkodierung: Text. Ein Signaturgeheimnis ist eine Zeichenkette, die Stripe gewählt hat, und obwohl es zufällig aussieht, ist es weder Hex noch Base64; als eines von beiden gelesen ergibt es andere Bytes und eine Signatur, die zu nichts passt.
- Zu prüfende Signatur: allein das v1-Element, nicht der ganze Header. v1= lässt sich unverändert einfügen, weil dieses Etikett genauso entfernt wird wie sha256= — der vollständige Header aber nicht, weil das führende t= als Etikett gelesen wird und was danach folgt überhaupt keine Signatur ist.
Drei weitere Dinge über diesen Header sollte man wissen, bevor man irgendetwas anderes untersucht. Ignorieren Sie jedes Schema außer v1: das v0-Element bei Testereignissen ist absichtlich keine echte Signatur, und alles Übrige zu ignorieren ist genau das, was verhindert, dass Ihnen ein schwächeres Schema aufgezwungen wird. Während ein Endpunktgeheimnis gewechselt wird, sind beide bis zu einen Tag lang gültig, und der Header trägt ein v1-Element pro Geheimnis, von denen nur eines passt. Und jeder Auslieferungsversuch wird neu signiert, ein Wiederholungsversuch trägt also nicht die Signatur des ersten — der Zeitstempel innerhalb der signierten Zeichenkette ist auch das, was das Zurückweisen einer alten Signatur zu einem echten Schutz statt zu einer Geste macht, denn er lässt sich nicht ändern, ohne die Signatur zu zerstören.
Eine GitHub-Webhook-Signatur prüfen
GitHub ist das Einfügen, um das dieses Werkzeug herum gebaut wurde, und das einzige Rezept hier, das Sie von Anfang bis Ende überprüfen können, weil GitHub ein durchgerechnetes Beispiel veröffentlicht. Die Signatur kommt im Header X-Hub-Signature-256 als Etikett sha256= und dahinter ein Hex-Digest, und dieses Etikett wird hier erkannt und entfernt, sodass der Header-Wert genau so hineingeht, wie er ankam.
X-Hub-Signature-256: sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17
- Nachricht: der rohe Anfragerumpf, Byte für Byte. Das von GitHub veröffentlichte Beispiel signiert den Rumpf Hello, World! und nichts dahinter — kein abschließender Zeilenumbruch.
- Schlüssel: das Geheimnis, das Sie in den Einstellungen des Webhooks eingetragen haben, genau so, wie Sie es eingetragen haben. Das veröffentlichte Beispiel verwendet It's a Secret to Everybody.
- Schlüsselkodierung: Text. Ein GitHub-Geheimnis ist eine Zeichenkette, die Sie gewählt haben, also niemals Hex — selbst ein Geheimnis, das nur aus Hex-Ziffern besteht, wird als die eingetippten Zeichen gelesen.
- Zu prüfende Signatur: der ganze Header-Wert, sha256= inklusive. Hex wird ohne Rücksicht auf Groß- und Kleinschreibung verglichen, es ist also gleich, wie Ihre Logs es ausgeben.
Diese drei Werte zusammen sind die schnellste Plausibilitätsprüfung, die es gibt: fügen Sie sie ein, und diese Seite meldet eine Übereinstimmung mit HMAC-SHA-256 in Hex — womit Sie wissen, dass sowohl der Rechner als auch Ihr Verständnis des Rezepts stimmen, bevor Sie eines von beiden an einer echten Auslieferung versuchen. GitHub sendet außerdem einen älteren Header, X-Hub-Signature, der HMAC-SHA-1 über denselben Rumpf ist und nur aus Gründen der Altkompatibilität erhalten bleibt; weil diese Seite alle vier Digests auf einmal berechnet, wird eine Signatur aus jedem der beiden Header erkannt, ohne dass Sie sagen müssen, aus welchem. Was sie nicht retten kann, ist ein Rumpf, der als etwas anderes ankam als die Bytes, die GitHub gesendet hat — Nutzlasten können Zeichen außerhalb von ASCII enthalten, und beide Seiten müssen sie als UTF-8 lesen.
Eine Shopify-Webhook-Signatur prüfen
Shopify schreibt seinen Digest in Base64 statt in Hex, und das ist hier der einzige Unterschied, der zählt: dieselben 32 Bytes werden zu 44 Zeichen, die auf ein einzelnes Gleichheitszeichen enden, und dieses Zeichen ist Auffüllung und kein Etikett, es wird also nichts vorn abgeschnitten.
X-Shopify-Hmac-SHA256: dXEH6g6yUJ/CESIczphLijdXC211hsIsRvQ3nIsEPhc=
- Nachricht: der rohe Anfragerumpf, Byte für Byte so, wie er ausgeliefert wurde. Shopifys eigene Warnung betrifft Middleware, die den Rumpf parst — prüfen Sie zuerst und parsen Sie danach, denn ein Parser, der den Rumpf schon in ein Objekt verwandelt hat, hat die Bytes weggeworfen.
- Schlüssel: das Client-Geheimnis der App, zu der der Webhook gehört. Nicht ihr Zugriffstoken und nicht der API-Schlüssel daneben im selben Panel.
- Schlüsselkodierung: Text. Wie bei den anderen beiden ist das Geheimnis eine Zeichenkette und keine Kodierung von Bytes.
- Zu prüfende Signatur: der ganze Header-Wert. Er lässt sich unverändert einfügen, und weil gegen jeden Digest sowohl Hex als auch Base64 probiert wird, ist die Kodierung, die diese Seite zurückmeldet, selbst die Antwort darauf, in welcher Schreibweise der Absender ihn geschrieben hat.
Der Wert im Block oben steht dort, um die Form zu zeigen: es sind dieselben 32 Bytes wie im GitHub-Beispiel, nur in Base64 statt in Hex geschrieben. Das lohnt sich nebeneinander zu sehen, denn es ist der ganze Inhalt des Unterschieds zwischen den beiden Headern — ein Digest, zwei Schreibweisen —, und darum nennt diese Seite die Kodierung neben dem Algorithmus, statt Ihnen nur zu sagen, dass irgendetwas gepasst hat.
Häufig gestellte Fragen
- Meine Signatur passt nicht. Was prüfe ich zuerst?
- Die Schlüsselkodierung, dann die Bytes der Nachricht. Ein Geheimnis, das nach Hex aussieht, ist oft auch als Hex gemeint und nicht als Text, und beides ergibt völlig verschiedene Signaturen — ohne Fehlermeldung in die eine oder andere Richtung. Danach stellen Sie sicher, dass Sie den rohen Rumpf so signieren, wie er ankam, und nicht eine neu serialisierte Kopie.
- Warum wird SHA-1 hier angeboten, wenn das Hash-Werkzeug es gebrochen nennt?
- Weil HMAC nicht auf Kollisionsresistenz beruht — genau der Eigenschaft, die SHA-1 verloren hat. Seine Sicherheit kommt aus dem Schlüssel. HMAC-SHA-1 ist weiterhin solide und bei OAuth 1.0a und älterer AWS-Signierung im Einsatz, auch wenn SHA-256 für Neues die richtige Vorgabe ist.
- Ist ein längerer Digest sicherer?
- Nicht nennenswert. Die Stärke eines HMAC ist durch das Geheimnis begrenzt, nicht durch die Digest-Länge, also ist SHA-512 nicht viermal besser als SHA-256. Nehmen Sie den, den die Gegenseite erwartet.
- Was ist der Unterschied zwischen HMAC und einer digitalen Signatur?
- HMAC nutzt ein Geheimnis, das beide Seiten kennen; es belegt also, dass der Absender das Geheimnis kannte, aber nicht, welche Seite gesendet hat. Eine digitale Signatur nutzt einen privaten Schlüssel, den nur der Absender hat, sodass ein Dritter sie prüfen kann und der Absender sie nicht leugnen kann. Brauchen Sie diese letzte Eigenschaft, ist HMAC das falsche Werkzeug.
- Soll ich Signaturen mit === vergleichen?
- Nicht in einem Server. Ein gewöhnlicher Vergleich kehrt zurück, sobald sich Bytes unterscheiden, und dieses Timing verrät, wie viel einer geratenen Signatur stimmte. Nutzen Sie den Vergleich in konstanter Zeit Ihrer Plattform auf den rohen Bytes. Auf dieser Seite spielt es keine Rolle, weil Sie den Schlüssel ohnehin haben.
- Wird mein Schlüssel irgendwohin gesendet?
- Nein. Alles wird in Ihrem Browser mit der Web-Crypto-API berechnet; Nachricht und Schlüssel verlassen Ihr Gerät nie.
- Wie prüfe ich eine Stripe-Webhook-Signatur?
- Fügen Sie drei Dinge zu einer Zeichenkette zusammen — den Zeitstempel aus dem t=-Element des Headers, einen Punkt und den rohen Anfragerumpf — und signieren Sie diese mit dem Signaturgeheimnis des Endpunkts, als Text gelesen; dann vergleichen Sie das Ergebnis mit dem v1-Element des Headers. Der Abschnitt oben geht das Feld für Feld durch. Was die meisten stolpern lässt, ist der erste Schritt: der Rumpf allein ist nicht das, was Stripe signiert hat.
- Wie prüfe ich eine GitHub-Webhook-Signatur?
- Signieren Sie den rohen Anfragerumpf mit dem Geheimnis des Webhooks, als Text gelesen, mit SHA-256, und vergleichen Sie den Hex-Digest mit dem Header X-Hub-Signature-256. Das Etikett sha256= kann beim Einfügen hier dranbleiben. GitHub veröffentlicht ein durchgerechnetes Beispiel — den Rumpf Hello, World! mit dem Geheimnis It's a Secret to Everybody —, und das ist der schnellste Weg, Ihr Verständnis des Rezepts zu prüfen, bevor Sie es an einer echten Auslieferung versuchen.
- Wie prüfe ich eine Shopify-Webhook-Signatur?
- Signieren Sie den rohen Anfragerumpf mit dem Client-Geheimnis der App, zu der der Webhook gehört, als Text gelesen, mit SHA-256, und vergleichen Sie den Base64-Digest mit dem Header X-Shopify-Hmac-SHA256. Der ganze Header-Wert lässt sich unverändert einfügen — das abschließende Gleichheitszeichen ist Base64-Auffüllung. Passt es nicht, liegt es meist an Middleware, die den Rumpf geparst hat, bevor Ihr Handler ihn überhaupt gesehen hat.
- Wie prüfe ich eine Webhook-Signatur von einem beliebigen anderen Anbieter?
- Vier Fragen entscheiden es, und die Dokumentation des Absenders hat alle vier: welcher Header die Signatur trägt, welche Zeichenkette tatsächlich signiert wird, wie das Geheimnis gelesen werden soll und ob der Digest Hex oder Base64 ist. Tragen Sie das in die Felder oben ein. Passt es dann noch nicht, ist die Antwort fast immer die zweite — sehr viele Absender signieren den Rumpf mit etwas daran angefügt statt den Rumpf allein.
Verwandte Werkzeuge
- TOTP-/2FA-Code-Debugger
Erzeuge und debugge 2FA-Codes, mit der vollständigen Ableitung.
- Bcrypt
Einen bcrypt-Hash erzeugen oder ein Passwort dagegen prüfen.
- JWT-Decoder / -Verifizierer
Dekodiert und verifiziert JSON Web Tokens – Signatur und Claims.
- Hash-Generator
MD5, SHA-1, SHA-256, SHA-384 und SHA-512 auf einmal.