HMAC vs. digitale Signatur ist die wichtigste Designentscheidung bei jedem Verfahren zur Nachrichtenauthentifizierung, und es geht dabei um Vertrauen, nicht um Geschwindigkeit. Ein HMAC-Tag wird mit demselben geheimen Schlüssel berechnet und geprüft; wer prüfen kann, kann also auch fälschen. Eine Signatur wird mit einem privaten Schlüssel erstellt und mit einem öffentlichen Schlüssel geprüft; Verifizierer können also keine neuen gültigen Nachrichten erzeugen.
Auf einen Blick
| HMAC (RFC 2104, FIPS 198-1) | Digitale Signatur | |
|---|---|---|
| Schlüssel | Ein gemeinsames Geheimnis | Privater Schlüssel signiert, öffentlicher Schlüssel prüft |
| Wer ein gültiges Tag oder eine gültige Signatur erzeugen kann | Jeder, der das Geheimnis besitzt, auch jeder Verifizierer | Nur der Inhaber des privaten Schlüssels |
| Nichtabstreitbarkeit (gegenüber Dritten nachweisbar) | Nein | Ja, sofern der Schlüssel vertrauenswürdig an den Signierer gebunden ist |
| Schlüsselverteilung | Das Geheimnis muss jeden Verifizierer vertraulich erreichen | Der öffentliche Schlüssel kann veröffentlicht werden (JWKS, Zertifikat, DNS) |
| Größe des Nachweises | 32 Byte bei HMAC-SHA256 | 64 Byte (Ed25519, ECDSA P-256), 256–512 Byte (RSA) |
| Geschwindigkeit, ein Kern eines Apple M4 Max | etwa 7 Millionen Tags pro Sekunde bei 256-Byte-Nachrichten (OpenSSL 3.6.5) | etwa 60.000 Ed25519- oder 87.000 P-256-Signaturen pro Sekunde |
| Typische Einsatzzwecke | Webhooks, Session-Cookies, AWS SigV4, TOTP, HS256-JWTs, Record-MACs in TLS 1.2 | TLS-Zertifikate und -Handshakes, ID-Tokens in OIDC, Paketsignierung, Git, Passkeys |
| Post-Quanten-Sicherheit | Sicher mit SHA-256 (Grover halbiert nur den Aufwand für Urbilder) | Klassische Verfahren werden durch Shor gebrochen; nötig ist ML-DSA oder Vergleichbares |
HMAC-Durchsatz gemessen mit openssl speed -hmac sha256 (etwa 1,83 GB/s bei 256-Byte-Eingaben), Signaturraten mit openssl speed.
Der Unterschied liegt im Vertrauensmodell
Ein HMAC ist ein Hash mit Schlüssel: H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ m)). Sein Sicherheitsziel ist, dass niemand ohne den Schlüssel ein gültiges Tag erzeugen kann. Das genügt, wenn genau zwei Parteien den Schlüssel teilen und darauf vertrauen, dass die jeweils andere nichts fälscht, denn ein gültiges Tag bedeutet dann „die andere Partei hat das gesendet“. Ab drei Parteien bricht das Modell zusammen: Jeder Verifizierer kann sich gegenüber den anderen als Absender ausgeben, und im Streitfall kann der Absender behaupten, der Empfänger habe das Tag erzeugt.
Eine digitale Signatur trennt die Fähigkeiten. Wer den Prüfschlüssel veröffentlicht, hilft damit niemandem beim Signieren. Ein einzelner Aussteller kann also Tausende Verifizierer bedienen, und eine Signatur lässt sich einem Auditor oder einem Gericht als Beleg der Herkunft vorlegen, sofern der Schlüssel durch ein Zertifikat, ein Schlüsselverzeichnis oder einen Kontoeintrag an den Signierer gebunden war. Wegen dieser Trennung werden Identitätstokens, die viele Dienste verarbeiten, signiert – etwa ID-Tokens von OpenID Connect oder Access Tokens, die Ressourcenserver prüfen. Aus demselben Grund ist eine nach außen gelangte Konfiguration eines Verifizierers bei Signaturen harmlos, bei HMAC dagegen katastrophal.
Praktische Aspekte
Schlüsselmanagement. HMAC-Geheimnisse müssen zufällig erzeugt werden (mindestens 256 Bit für HMAC-SHA256; RFC 7518 §3.2 verlangt das für HS256), vertraulich übertragen, von jedem Verifizierer gespeichert und überall gleichzeitig rotiert werden, oder mit einer Übergangsfrist, in der zwei Geheimnisse gültig sind. Bei Signaturschlüsseln bleibt die private Hälfte an einem Ort, idealerweise in einem HSM oder KMS, und die Rotation läuft über Schlüssel-IDs in einem veröffentlichten Schlüsselsatz.
Leistung und Größe. Ein HMAC besteht aus zwei Hash-Berechnungen: Millionen pro Sekunde und Kern, mit einem 32-Byte-Tag. Signaturen kosten einige Dutzend Mikrosekunden und sind 64 Byte groß oder größer. Für den meisten Webverkehr spielt beides keine Rolle; wichtig wird es bei der Authentifizierung jedes einzelnen Pakets oder bei interner Kommunikation mit sehr hohem Nachrichtenaufkommen, wo HMAC oder ein AEAD die Regel ist.
Fallstricke. Ein HMAC muss in konstanter Zeit verglichen werden, darf nicht durch hash(key ‖ message) ersetzt werden (eine Konstruktion, die ein Length-Extension-Angriff auf SHA-256 bricht) und muss genau die empfangenen Bytes authentifizieren (den rohen Body der Anfrage, kein neu serialisiertes JSON-Objekt). Signaturen müssen mit einem Algorithmus geprüft werden, den der Verifizierer festlegt, nie mit einem, den die Nachricht wählt.
Das folgende Skript, ausgeführt mit Node.js 26.10, authentifiziert denselben Webhook-Body auf beide Arten.
import { createHmac, generateKeyPairSync, randomBytes, sign, timingSafeEqual, verify } from "node:crypto";
const body = Buffer.from('{"event":"invoice.paid","id":"evt_123"}');
// HMAC: sender and receiver share one secret (in production it comes from a secret store).
const secret = randomBytes(32);
const tag = createHmac("sha256", secret).update(body).digest();
const expected = createHmac("sha256", secret).update(body).digest();
console.log("HMAC-SHA256 tag:", tag.length, "bytes, valid:", timingSafeEqual(tag, expected));
// Signature: sender keeps the private key, receivers hold only the public key.
const { privateKey, publicKey } = generateKeyPairSync("ed25519");
const signature = sign(null, body, privateKey);
console.log("Ed25519 signature:", signature.length, "bytes, valid:", verify(null, body, publicKey, signature));
HMAC-SHA256 tag: 32 bytes, valid: true
Ed25519 signature: 64 bytes, valid: true
Das HMAC-Geheimnis muss mit jedem Verifizierer geteilt werden; der private Ed25519-Schlüssel verlässt den Absender nie, verteilt wird nur der öffentliche Schlüssel mit 32 Byte.
Webhooks und APIs in der Praxis
Die meisten Webhook-Anbieter nutzen HMAC, weil jeder Abonnent ein eigenes Geheimnis bekommt: GitHub sendet X-Hub-Signature-256: sha256=, gefolgt von einem hexadezimalen HMAC-SHA256 des Bodys, und Stripe signiert im Header Stripe-Signature einen Zeitstempel samt Body, damit Empfänger Replays ablehnen können. Da das Geheimnis jedes Abonnenten einzigartig ist, tritt das Mehrparteienproblem nicht auf. Signierte Webhooks auf Basis von HTTP Message Signatures (RFC 9421) oder JWS kommen dort vor, wo ein Absender mit vielen Empfängern kommuniziert, die kein Geheimnis teilen sollen, oder wo Empfänger prüfen wollen, ohne Geheimnisse bereitzustellen. AWS Signature Version 4 signiert Anfragen auf Basis von HMAC; OAuth DPoP und Web Bot Auth nutzen Signaturen, weil sich der Verifizierer nicht als Client ausgeben können darf.
Wann welches Verfahren passt
- Derselbe Dienst stellt aus und prüft (Session-Cookies, CSRF-Tokens, interne JWTs): HMAC-SHA256.
- Ein Absender, ein Empfänger, Geheimnis auf separatem Weg geteilt (Webhooks pro Kunde): HMAC mit einem Zeitstempel in den signierten Daten.
- Ein Aussteller, viele Verifizierer (Identitätstokens, öffentliche APIs, mobile Apps, die Daten vom Server prüfen): Signaturen, mit in einem JWKS veröffentlichten Schlüsseln.
- Nachweise für Dritte (Verträge, Audit-Logs, Software-Releases): Signaturen plus vertrauenswürdige Zeitstempel.
- Clients, von denen sich keiner als ein anderer ausgeben können darf (DPoP, Bot-Authentifizierung, Geräteattestierung): Signaturen mit eigenen Schlüsseln pro Client.
- Sehr hohe Nachrichtenraten über eine vertrauenswürdige Verbindung: HMAC oder ein AEAD.
Hinweise zur Migration
Der Wechsel von HMAC zu Signaturen steht meist an, wenn ein zweiter Verifizierer hinzukommt oder ein Geheimnis durchsickert.
- Führe eine Algorithmuskennung ein, falls dein Format keine hat (
algin JOSE, einen Parameteralgin HTTP-Signaturen, ein Versionspräfix), damit Verifizierer erkennen, welches Verfahren eine Nachricht nutzt, ohne ihr blind zu vertrauen. - Veröffentliche den öffentlichen Schlüssel mit einer Schlüssel-ID (JWKS, Schlüsselverzeichnis für HTTP-Signaturen) und gib den Verifizierern Zeit, ihn abzurufen.
- Signiere während des Übergangs doppelt: Sende sowohl den HMAC-Header als auch die Signatur und lass die Verifizierer die Signatur bevorzugen.
- Entferne das gemeinsame Geheimnis von Verifizierern, die nur prüfen müssen; genau darin liegt der Sicherheitsgewinn, also behalte es nicht „für alle Fälle“.
- Nutze nie einen Schlüssel für beide Verfahren. Ein öffentlicher RSA-Schlüssel, der als HMAC-Geheimnis wiederverwendet wird, ist genau die Algorithm Confusion, die JWT-Bibliotheken angreifbar gemacht hat; siehe HS256 vs. RS256.