Keine Werbung mögen? Gehen Werbefrei Heute

HMAC Wie Webhooks wissen, dass Sie nicht lügen

Veröffentlicht am

Jedes Mal, wenn GitHub, Stripe oder Shopify ein Webhook an Ihren Server senden, signieren sie den Payload mit HMAC. Hier ist genau, wie das funktioniert – und wie man es in eigener Code-Logik überprüft.

Jedes Mal, wenn GitHub, Stripe oder Shopify einen Webhook an Ihren Server senden, signieren sie den Payload mit HMAC. Hier ist genau, wie es funktioniert – und wie Sie es in Ihrem eigenen Code überprüfen können.
ANZEIGE Entfernen?

Sie erhalten eine POST-Anfrage, die behauptet, von Stripe zu stammen. Der Payload sagt, ein Zahlungserfolg sei erfolgt. Sie verarbeiten die Bestellung, versenden die Waren – und drei Tage später stellen Sie fest, dass die Anfrage gefälscht wurde. Ouch.

Deswegen signiert jeder ernsthafte Webhook-Anbieter seine Payloads mit HMAC. Wenn Sie HMAC verstehen, verstehen Sie, warum GitHub, Stripe, Shopify, Twilio und praktisch jede moderne API es verwendet – und Sie wissen genau, wie Sie diese Signaturen in Ihrem eigenen Servercode überprüfen können.

Was HMAC tatsächlich ist

HMAC steht für Hash-basierte Nachrichtenauthentifizierungscode. Es beantwortet eine Frage: „Hat die Person, die mir diese Nachricht geschickt hat, das gemeinsame Geheimnis gekannt?“

Es funktioniert durch die Durchführung eines kryptographischen Hash-Funktion – normalerweise SHA-256 – über die Kombination aus einem geheimen Schlüssel und dem Nachrichtentext. Das Ergebnis ist ein fester Längenstring, der:

  • vollständig verändert wird wenn sich ein einzelner Byte des Nachrichtentexts ändert
  • nicht erzeugt werden kann ohne den geheimen Schlüssel zu kennen
  • nicht rückgängig gemacht werden kann um den Schlüssel oder den ursprünglichen Nachrichtentext zu enthüllen

Die Formel ist kompakt: HMAC(key, message) = H((key ⊕ opad) || H((key ⊕ ipad) || message)). Sie müssen die inneren Details nicht auswendig lernen – jede Sprache bietet eine Standardbibliothek mit Implementierung – aber es hilft, den Zweck zu verstehen: Der Schlüssel wird zweimal in unterschiedlicher Weise in den Hash eingebaut, um eine Klasse von Angriffen namens „Length-Extension-Attacken“ zu verhindern.

Wie ein Webhook-Anbieter es verwendet

Wenn Sie einen Webhook-Endpunkt registrieren, gibt der Anbieter Ihnen ein Signiergeheimnis – eine zufällige Zeichenkette, die nur Sie und er kennen. Wenn ein Ereignis ausgelöst wird:

  1. Der Anbieter serialisiert den Ereignis-Payload in JSON (oder eine kanonische Zeichenkette).
  2. Er berechnet HMAC-SHA256(secret, payload).
  3. Er sendet die Anfrage mit der Signatur in einem Header – X-Hub-Signature-256 für GitHub, Stripe-Signature für Stripe und so weiter.

Auf Ihrer Seite führen Sie dieselbe Berechnung über den rohen Anfragekörper durch und vergleichen sie. Wenn sie übereinstimmen, ist der Payload authentisch. Wenn nicht, wird er verworfen.

Überprüfung im Code

Hier ist, wie die Überprüfung in den häufigsten Sprachen aussieht. Das Muster ist in jeder Sprache identisch: Berechnen und mit einer zeitunabhängigen Funktion vergleichen.

Node.js

const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)          // rawBody must be a Buffer or string — NOT parsed JSON
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Python

import hmac
import hashlib

def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, signature)

PHP

function verifyWebhook(string $rawBody, string $signature, string $secret): bool {
    $expected = hash_hmac('sha256', $rawBody, $secret);
    return hash_equals($expected, $signature);
}

Das entscheidende Detail: Verwenden Sie den rohen Körper

Der häufigste Implementierungsfehler ist, einen geparschten und erneut serialisierten Payload an die HMAC-Funktion zu übergeben, anstatt die ursprünglichen rohen Bytes. Reihenfolge der Schlüssel, Leerzeichen und Unicode-Verarbeitung beeinflussen den Hash. Der Anbieter hat die exakten Bytes, die er über das Netzwerk gesendet hat – Sie müssen genau diese gleichen Bytes hashen.

In Express (Node.js) bedeutet das, dass der Body-Parser so konfiguriert wird, dass der rohe Buffer erhalten bleibt:

app.use('/webhooks', express.raw({ type: 'application/json' }));

In Django verwenden Sie request.body statt request.data. In Flask verwenden Sie request.get_data().

Warum nicht einfach einen normalen Hash?

Ein einfacher SHA-256-Hash des Payloads beweist nichts – jeder kann den Hash berechnen SHA256(payload) ohne ein Geheimnis. Der geheime Schlüssel von HMAC macht es zu einem Authentifizierung Code, nicht nur einem Prüfsumme. Er beantwortet „Wer hat dies gesendet?“ statt nur „War die Nachricht im Transit korrupt?“.

Warum nicht asymmetrische Signaturen (wie RSA)?

RSA und ECDSA ermöglichen es dem Empfänger, eine Signatur zu überprüfen, ohne den privaten Schlüssel zu kennen – das ist wertvoll für öffentliche Broadcasts (wie Code-Verifizierung). Bei Webhooks gibt es nur zwei Parteien, die jemals die Signatur überprüfen müssen: Sie und der Anbieter. Ein gemeinsamer geheimer Schlüssel ist einfacher, schneller und genauso sicher in diesem Modell. Einige Anbieter (Svix, Clerk) bieten asymmetrische Webhook-Verifikation an, falls Sie ein Geheimnis nicht sicher auf Serverseite speichern können.

Replay-Angriffe – und wie man sie verhindert

Ein gültiger HMAC-Hash beweist Authentizität, aber nicht Frische. Ein Angreifer, der eine gültige signierte Anfrage erfährt, kann sie später wiederholen. Stripe verhindert dies, indem er eine Uhrzeit in der Stripe-Signature Header einbezieht und die Uhrzeit zusammen mit dem Payload-Body hashen. Auf Ihrer Seite lehnen Sie jede Anfrage ab, bei der die Uhrzeit mehr als fünf Minuten alt ist.

Wenn Sie ein eigenes Webhook-System bauen, machen Sie das gleiche: Fügen Sie eine monoton steigende Nonce oder eine Unix-Uhrzeit in die signierte Nachricht ein und lehnen Sie alte Anfragen auf Serverseite ab.

Zeitunabhängige Vergleiche sind nicht optional

Vergleichen Sie niemals HMAC-Hashes mit einem einfachen Gleichheitscheck (===, ==). String-Vergleiche mit kurzen Schleifen verlieren Informationen über die Anzahl der übereinstimmenden führenden Bytes – ein Angreifer, der tausende von Anfragen macht, kann den erwarteten Hash Byte für Byte rekonstruieren. Verwenden Sie immer eine zeitunabhängige Vergleichsfunktion:

  • Node.js: crypto.timingSafeEqual()
  • Python: hmac.compare_digest()
  • PHP: hash_equals()
  • Go: hmac.Equal()
  • Ruby: ActiveSupport::SecurityUtils.secure_compare()

Zusammenfassung: ein produktionssicherer Webhook-Handler

Hier ist ein vollständiges Beispiel mit dem GitHub-Header in Node.js: X-Hub-Signature-256 Schnellreferenz: wer verwendet was

const express = require('express');
const crypto = require('crypto');

const app = express();
const WEBHOOK_SECRET = process.env.GITHUB_WEBHOOK_SECRET;

// Keep the body as raw bytes — critical!
app.use('/github/webhook', express.raw({ type: 'application/json' }));

app.post('/github/webhook', (req, res) => {
  const sigHeader = req.headers['x-hub-signature-256'];
  if (!sigHeader) return res.status(401).send('Missing signature');

  const sig = sigHeader.replace('sha256=', '');
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  // Safe to process the event now
  console.log('Event type:', req.headers['x-github-event']);

  res.sendStatus(200);
});

app.listen(3000);

Anbieter

Uhrzeit in der Signatur?KopfbereichAlgorithmusX-Hub-Signature-256
GitHubStripe-SignatureHMAC-SHA256NEIN
StripeX-Shopify-Hmac-Sha256HMAC-SHA256Ja
ShopifyX-Twilio-SignatureHMAC-SHA256NEIN
TwilioX-Slack-SignatureHMAC-SHA1NEIN
LockerPaddleHMAC-SHA256Ja
Paddle-SignatureHMAC: Wie Webhooks wissen, dass Sie nicht lügen 2HMAC-SHA256Ja
Möchten Sie werbefrei genießen? Werde noch heute werbefrei

Erweiterungen installieren

IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche

Zu Chrome-Erweiterung Zu Kantenerweiterung Zu Firefox-Erweiterung Zu Opera-Erweiterung

Die Anzeigetafel ist eingetroffen!

Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!

ANZEIGE Entfernen?
ANZEIGE Entfernen?
ANZEIGE Entfernen?

Nachrichtenecke mit technischen Highlights

Beteiligen Sie sich

Helfen Sie uns, weiterhin wertvolle kostenlose Tools bereitzustellen

Kauf mir einen Kaffee
ANZEIGE Entfernen?