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 StrCmp prü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.randRandBytesExact generieren, nie hartkodieren.

Letzte Aktualisierung: 2026-06-06