std.crypto.hmac — HMAC-SHA256
import std.crypto.hmac;
HMAC-SHA256 nach RFC 2104 / FIPS 198-1. Kombiniert einen geheimen Schlüssel mit einer Nachricht zu einem Message Authentication Code (MAC) — schützt sowohl Integrität als auch Authentizität der Daten.
Abhängigkeit: std.crypto.sha256.
→ std.crypto Paket · std.crypto.sha256 · std.crypto.rand
Funktionen
| Funktion | Signatur | Beschreibung |
|---|---|---|
HMAC_SHA256 | (key: int64, keyLen: int64, data: int64, dataLen: int64, out: int64): void | Schreibt 32-Byte-MAC in out |
HMAC_SHA256_Hex | (key: int64, keyLen: int64, data: int64, dataLen: int64, out: int64): void | Schreibt 64-Zeichen Lowercase-Hex + NUL in out (65 Bytes) |
Schlüssel beliebiger Länge sind gültig. Schlüssel > 64 Bytes werden intern mit SHA-256 auf 32 Bytes komprimiert. Empfohlen: 32 Bytes.
Verwendung
Nachricht authentifizieren
import std.crypto.hmac;
import std.alloc;
fn main(): int64 {
var key: pchar := "geheim";
var data: pchar := "Nachricht die authentifiziert werden soll";
var mac: int64 := alloc(32);
HMAC_SHA256(key as int64, 6, data as int64, 41, mac);
// mac: 32-Byte-HMAC — zum Senden oder Vergleichen
free(mac, 32);
return 0;
}
Hex-Ausgabe (z.B. für HTTP-Header)
import std.crypto.hmac;
import std.alloc;
import std.io;
fn SignRequest(key: pchar, keyLen: int64, body: pchar, bodyLen: int64): void {
var hex: int64 := alloc(65);
HMAC_SHA256_Hex(key as int64, keyLen, body as int64, bodyLen, hex);
PrintStr("X-Signature: ");
PrintStr(hex as pchar);
PrintStr("\n");
free(hex, 65);
}
MAC-Vergleich (konstante Zeit)
import std.crypto.hmac;
import std.alloc;
// Zeitkonstanter Vergleich — verhindert Timing-Angriffe
fn HmacEqual(a: int64, b: int64): bool {
var diff: int64 := 0;
var i: int64 := 0;
while (i < 32) {
diff := diff | (peek8(a + i) ^ peek8(b + i));
i := i + 1;
}
return diff = 0;
}
fn VerifyHmac(key: pchar, keyLen: int64,
data: pchar, dataLen: int64,
expectedMac: int64): bool {
var computed: int64 := alloc(32);
HMAC_SHA256(key as int64, keyLen, data as int64, dataLen, computed);
var ok: bool := HmacEqual(computed, expectedMac);
free(computed, 32);
return ok;
}
Abgeleiteten Schlüssel erzeugen (einfaches HKDF-Extract)
import std.crypto.hmac;
import std.alloc;
// HKDF-Extract-Schritt: PRK = HMAC-SHA256(salt, inputKeyMaterial)
fn HKDFExtract(salt: pchar, saltLen: int64,
ikm: int64, ikmLen: int64,
prk: int64): void {
HMAC_SHA256(salt as int64, saltLen, ikm, ikmLen, prk);
}
Hinweise
- MAC ≠ Signatur: HMAC authentifiziert, wer den geheimen Schlüssel kennt. Für asymmetrische Signaturen (Dritte können verifizieren ohne Schlüsselkenntnis) → std.crypto.ecc (ECDSA).
- AES-CBC + HMAC: AES-CBC verschlüsselt, aber authentifiziert nicht. Für encrypt-then-MAC: zuerst verschlüsseln, dann HMAC über den Chiffretext berechnen und mitsenden.
- Konstanter Zeitvergleich: MACs niemals mit direktem Byte-Vergleich oder
StrCmpprüfen — Timing-Angriffe können den Schlüssel offenlegen. Immer alle 32 Bytes vergleichen (wie im Beispiel oben). - Schlüssellänge: Empfohlen sind 32 Bytes (= SHA-256-Ausgabelänge). Kürzere Schlüssel reduzieren die Sicherheit; längere werden intern auf 32 Bytes gehasht.
- Schlüssel geheim halten: Der HMAC-Schlüssel ist das Geheimnis — mit
std.crypto.rand→RandBytesExactgenerieren, nie hartkodieren.
Letzte Aktualisierung: 2026-06-06
