KeyDerivationExtensions

Namespace: WvdS.System.Security.Cryptography.KeyDerivation

Statische Klasse für Schlüsselableitung (Key Derivation Functions) mit Post-Quantum Support. Unterstützt HKDF, PBKDF2 und Argon2id.

Übersicht

Unterstützte KDF-Algorithmen:

KDF Standard Verwendung
HKDF RFC 5869 Session-Keys aus Shared Secrets
PBKDF2 RFC 8018 Passwort-basierte Schlüssel
Argon2id RFC 9106 Memory-hard KDF (Passwörter)

HKDF - Hash-based Key Derivation

DeriveKey

Leitet Schlüssel aus einem Shared Secret ab (HKDF-Extract-then-Expand).

// ML-KEM Shared Secret aus Key Exchange
byte[] sharedSecret = session.SharedSecret;
 
// Standard-Ableitung (SHA-256)
byte[] aesKey = KeyDerivationExtensions.DeriveKey(
    sharedSecret,
    outputLength: 32);  // 256 Bit
 
// Mit Salt und Context-Info
byte[] salt = RandomNumberGenerator.GetBytes(32);
byte[] info = Encoding.UTF8.GetBytes("MyApp-Session-Key");
 
byte[] sessionKey = KeyDerivationExtensions.DeriveKey(
    sharedSecret,
    outputLength: 32,
    salt: salt,
    info: info,
    hashAlgorithm: HashAlgorithmName.SHA384);  // Optional

HkdfExtract

Extrahiert PRK (Pseudorandom Key) aus Input Key Material.

byte[] inputKeyMaterial = GetSharedSecret();
byte[] salt = RandomNumberGenerator.GetBytes(32);
 
byte[] prk = KeyDerivationExtensions.HkdfExtract(
    inputKeyMaterial,
    salt: salt,
    hashAlgorithm: HashAlgorithmName.SHA256);
 
// PRK hat gleiche Länge wie Hash-Output (32 Bytes bei SHA-256)

HkdfExpand

Expandiert PRK zu Output Key Material.

byte[] prk = GetPrk();
 
// Encryption Key
byte[] encKey = KeyDerivationExtensions.HkdfExpand(
    prk,
    outputLength: 32,
    info: Encoding.UTF8.GetBytes("encryption"));
 
// MAC Key
byte[] macKey = KeyDerivationExtensions.HkdfExpand(
    prk,
    outputLength: 32,
    info: Encoding.UTF8.GetBytes("mac"));

Hybrid Key Derivation

Kombiniert klassische (ECDH/DH) und PQ (ML-KEM) Shared Secrets.

DeriveHybridKey

byte[] ecdhSecret = GetEcdhSharedSecret();
byte[] mlKemSecret = GetMlKemSharedSecret();
 
// Hybrid-Modus: Beide Secrets werden kombiniert
byte[] hybridKey = KeyDerivationExtensions.DeriveHybridKey(
    classicSecret: ecdhSecret,
    pqSecret: mlKemSecret,
    outputLength: 32,
    mode: CryptoMode.Hybrid);
 
// Nur klassisch
byte[] classicKey = KeyDerivationExtensions.DeriveHybridKey(
    classicSecret: ecdhSecret,
    pqSecret: null,
    outputLength: 32,
    mode: CryptoMode.Classic);
 
// Nur Post-Quantum
byte[] pqKey = KeyDerivationExtensions.DeriveHybridKey(
    classicSecret: null,
    pqSecret: mlKemSecret,
    outputLength: 32,
    mode: CryptoMode.PostQuantum);
 
// Custom Info
byte[] customKey = KeyDerivationExtensions.DeriveHybridKey(
    classicSecret: ecdhSecret,
    pqSecret: mlKemSecret,
    outputLength: 64,
    mode: CryptoMode.Hybrid,
    info: Encoding.UTF8.GetBytes("MyProtocol-v1"));

Schlüssel-Kombination:

Hybrid Mode:
  IKM = classicSecret || pqSecret
  Key = HKDF-SHA256(IKM, info="WvdS-Hybrid-Key")

DeriveHybridKeyMaterial

Leitet mehrere Schlüssel für verschiedene Zwecke ab.

using HybridKeyMaterial keyMaterial = KeyDerivationExtensions.DeriveHybridKeyMaterial(
    classicSecret: ecdhSecret,
    pqSecret: mlKemSecret,
    mode: CryptoMode.Hybrid);
 
// Verwendung
byte[] encKey = keyMaterial.EncryptionKey;  // 32 Bytes
byte[] macKey = keyMaterial.MacKey;         // 32 Bytes
byte[] iv = keyMaterial.Iv;                 // 16 Bytes
byte[] authKey = keyMaterial.AuthKey;       // 32 Bytes
 
// IDisposable: Schlüssel werden sicher gelöscht

PBKDF2 - Passwort-basierte Ableitung

Pbkdf2

string password = "SecurePassword123!";
byte[] salt = RandomNumberGenerator.GetBytes(32);
 
// Standard PBKDF2
byte[] key = KeyDerivationExtensions.Pbkdf2(
    password,
    salt,
    iterations: 100000,
    outputLength: 32);
 
// Mit PQ-Entropy (zusätzlicher Schutz)
byte[] pqEntropy = GetPqEntropy();
 
byte[] enhancedKey = KeyDerivationExtensions.Pbkdf2(
    password,
    salt,
    iterations: 100000,
    outputLength: 32,
    pqEntropy: pqEntropy,  // Wird mit Salt kombiniert
    hashAlgorithm: HashAlgorithmName.SHA512);

Pbkdf2WithPqSalt

PBKDF2 mit PQ-verstärktem Salt (Public Key wird in Salt-Berechnung einbezogen).

string password = "UserPassword";
byte[] baseSalt = RandomNumberGenerator.GetBytes(16);
byte[] mlKemPublicKey = GetRecipientPublicKey();
 
// Salt = SHA256(baseSalt || pqPublicKey)
byte[] key = KeyDerivationExtensions.Pbkdf2WithPqSalt(
    password,
    baseSalt,
    mlKemPublicKey,
    iterations: 100000,
    outputLength: 32);
Vorteil: Selbst bei identischem Passwort und Base-Salt ergibt sich für jeden Empfänger (unterschiedlicher PQ Public Key) ein anderer Schlüssel.

Argon2id - Memory-Hard KDF

Argon2id via OpenSSL 3.6 - widerstandsfähig gegen GPU/ASIC-Angriffe.

Argon2id (Byte-Array)

byte[] password = Encoding.UTF8.GetBytes("SecurePassword");
byte[] salt = RandomNumberGenerator.GetBytes(16);  // Mindestens 16 Bytes
 
byte[] key = KeyDerivationExtensions.Argon2id(
    password,
    salt,
    outputLength: 32,     // Key-Länge
    iterations: 3,        // Zeit-Kosten (t)
    memoryKiB: 65536,     // Speicher: 64 MB
    parallelism: 4);      // Threads (p)

Argon2id (String)

string password = "UserPassword123";
byte[] salt = RandomNumberGenerator.GetBytes(16);
 
byte[] key = KeyDerivationExtensions.Argon2id(
    password,
    salt,
    outputLength: 32,
    iterations: 3,
    memoryKiB: 65536,
    parallelism: 4);

Empfohlene Parameter:

Anwendung Iterations (t) Memory (m) Parallelism (p)
Passwort-Hashing 3 64 MB 4
Hohe Sicherheit 4 256 MB 4
Low-Memory 4 16 MB 4

TLS Key Derivation

DeriveTlsKeys (TLS 1.2 Style)

byte[] preMasterSecret = GetPreMasterSecret();
byte[] clientRandom = GetClientRandom();
byte[] serverRandom = GetServerRandom();
 
using TlsKeyMaterial keys = KeyDerivationExtensions.DeriveTlsKeys(
    preMasterSecret,
    clientRandom,
    serverRandom,
    mode: CryptoMode.Hybrid);
 
// Verwendung
var clientKey = keys.ClientWriteKey;   // 32 Bytes
var serverKey = keys.ServerWriteKey;   // 32 Bytes
var clientIv = keys.ClientWriteIv;     // 12 Bytes
var serverIv = keys.ServerWriteIv;     // 12 Bytes

DeriveTls13Keys

TLS 1.3 kompatible Key Schedule.

byte[]? pskSecret = null;  // Pre-Shared Key (optional)
byte[] ecdhSecret = GetEcdhSecret();
byte[] pqSecret = GetMlKemSecret();
byte[] clientHello = GetClientHelloBytes();
byte[] serverHello = GetServerHelloBytes();
 
using Tls13KeySchedule schedule = KeyDerivationExtensions.DeriveTls13Keys(
    pskSecret,
    ecdhSecret,
    pqSecret,
    clientHello,
    serverHello,
    mode: CryptoMode.Hybrid);
 
// Handshake Traffic Secrets
var clientHsSecret = schedule.ClientHandshakeTrafficSecret;
var serverHsSecret = schedule.ServerHandshakeTrafficSecret;
 
// Application Traffic Secrets
var clientAppSecret = schedule.ClientApplicationTrafficSecret;
var serverAppSecret = schedule.ServerApplicationTrafficSecret;
 
// Resumption Secret
var resumptionSecret = schedule.ResumptionMasterSecret;

Datenklassen

HybridKeyMaterial

Container für abgeleitete Schlüssel mit sicherer Speicherbereinigung.

Eigenschaft Typ Länge Beschreibung
EncryptionKey byte[] 32 AES-Schlüssel
MacKey byte[] 32 HMAC-Schlüssel
Iv byte[] 16 Initialisierungsvektor
AuthKey byte[] 32 Authentifizierungsschlüssel
using HybridKeyMaterial keys = DeriveKeys();
 
// Keys werden bei Dispose() sicher gelöscht
// (CryptographicOperations.ZeroMemory)

TlsKeyMaterial

TLS 1.2 Style Schlüsselmaterial.

Eigenschaft Typ Beschreibung
MasterSecret byte[] 48 Bytes Master Secret
ClientWriteKey byte[] Client-seitiger Verschlüsselungsschlüssel
ServerWriteKey byte[] Server-seitiger Verschlüsselungsschlüssel
ClientWriteIv byte[] Client-seitiger IV
ServerWriteIv byte[] Server-seitiger IV
ClientWriteMacKey byte[] Client MAC Key (leer bei GCM)
ServerWriteMacKey byte[] Server MAC Key (leer bei GCM)

Tls13KeySchedule

TLS 1.3 Key Schedule.

Eigenschaft Typ Beschreibung
ClientHandshakeTrafficSecret byte[]? Client Handshake Traffic Secret
ServerHandshakeTrafficSecret byte[]? Server Handshake Traffic Secret
ClientApplicationTrafficSecret byte[]? Client Application Traffic Secret
ServerApplicationTrafficSecret byte[]? Server Application Traffic Secret
ResumptionMasterSecret byte[]? Session Resumption Secret

Methoden-Übersicht

HKDF

Methode Parameter Rückgabe
DeriveKey byte[] sharedSecret, int outputLength, byte[]? salt, byte[]? info, HashAlgorithmName? byte[]
HkdfExtract byte[] ikm, byte[]? salt, HashAlgorithmName? byte[]
HkdfExpand byte[] prk, int outputLength, byte[]? info, HashAlgorithmName? byte[]

Hybrid

Methode Parameter Rückgabe
DeriveHybridKey byte[]? classicSecret, byte[]? pqSecret, int outputLength, CryptoMode, byte[]? info byte[]
DeriveHybridKeyMaterial byte[]? classicSecret, byte[]? pqSecret, CryptoMode HybridKeyMaterial

PBKDF2

Methode Parameter Rückgabe
Pbkdf2 string password, byte[] salt, int iterations, int outputLength, byte[]? pqEntropy, HashAlgorithmName? byte[]
Pbkdf2WithPqSalt string password, byte[] baseSalt, byte[] pqPublicKey, int iterations, int outputLength byte[]

Argon2id

Methode Parameter Rückgabe
Argon2id byte[] password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism byte[]
Argon2id string password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism byte[]

TLS

Methode Parameter Rückgabe
DeriveTlsKeys byte[] preMasterSecret, byte[] clientRandom, byte[] serverRandom, CryptoMode TlsKeyMaterial
DeriveTls13Keys byte[]? psk, byte[]? ecdh, byte[]? pq, byte[] clientHello, byte[] serverHello, CryptoMode Tls13KeySchedule

Vollständiges Beispiel

using WvdS.System.Security.Cryptography;
using WvdS.System.Security.Cryptography.KeyDerivation;
using WvdS.System.Security.Cryptography.KeyExchange;
 
// 1. Key Exchange durchführen
using var session = new KeyExchangeService();
await session.InitiateKeyExchangeAsync(recipientPublicKey, CryptoMode.Hybrid);
 
// 2. Hybrid Key Material ableiten
using HybridKeyMaterial keys = KeyDerivationExtensions.DeriveHybridKeyMaterial(
    classicSecret: session.ClassicSharedSecret,
    pqSecret: session.PqSharedSecret,
    mode: CryptoMode.Hybrid);
 
// 3. Schlüssel verwenden
using var aes = Aes.Create();
aes.Key = keys.EncryptionKey;
 
using var hmac = new HMACSHA256(keys.MacKey);
 
// 4. Verschlüsselung durchführen
// ...
 
// 5. Schlüssel werden automatisch sicher gelöscht

Sicherheitshinweise

  • Alle IDisposable Klassen implementieren CryptographicOperations.ZeroMemory
  • Argon2id benötigt OpenSSL 3.6 (nicht in .NET BCL verfügbar)
  • PBKDF2 mit weniger als 100.000 Iterationen wird nicht empfohlen
  • Salt muss bei PBKDF2/Argon2id immer zufällig und ausreichend lang sein (min. 16 Bytes)
Hybrid-Modus Sicherheit:

Im Hybrid-Modus wird der endgültige Schlüssel nur kompromittiert, wenn BEIDE Secrets (klassisch UND PQ) gebrochen werden. Dies bietet Schutz sowohl gegen klassische als auch gegen Quantenangriffe.

Siehe auch


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: den 29.01.2026 um 15:12