~~NOTOC~~
====== Szenario 11.1: Schlüsselgenerierung ======
**Kategorie:** [[.:start|Schlüsselmanagement]] \\
**Komplexität:** ⭐⭐⭐ (Mittel) \\
**Voraussetzungen:** OpenSSL 3.6+, sichere Entropiequelle \\
**Geschätzte Zeit:** 15-20 Minuten
----
===== Beschreibung =====
Dieses Szenario beschreibt die **sichere Generierung kryptographischer Schlüssel** für Post-Quantum-Algorithmen. Die Schlüsselgenerierung ist der kritischste Schritt - schwache Schlüssel gefährden alle darauf basierenden Operationen.
**Unterstützte Algorithmen:**
^ Algorithmus ^ Typ ^ Sicherheit ^ Schlüsselgröße (Public) ^
| **ML-DSA-44** | Signatur | 128-bit | 1,312 Bytes |
| **ML-DSA-65** | Signatur | 192-bit | 1,952 Bytes |
| **ML-DSA-87** | Signatur | 256-bit | 2,592 Bytes |
| **ML-KEM-512** | KEM | 128-bit | 800 Bytes |
| **ML-KEM-768** | KEM | 192-bit | 1,184 Bytes |
| **ML-KEM-1024** | KEM | 256-bit | 1,568 Bytes |
----
===== Workflow =====
flowchart LR
ENTROPY[Entropie-Quelle] --> RNG[CSPRNG]
RNG --> KEYGEN[Key Generation]
PARAM[Parameter wählen] --> KEYGEN
KEYGEN --> PUBKEY[Public Key]
KEYGEN --> PRIVKEY[Private Key]
PRIVKEY --> ENCRYPT[Verschlüsselt speichern]
style ENTROPY fill:#fff3e0
style ENCRYPT fill:#e8f5e9
----
===== Code-Beispiel: ML-DSA Signaturschlüssel =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using var ctx = PqCryptoContext.Initialize();
// ML-DSA-65 Schlüsselpaar generieren (empfohlen)
using var signatureKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
Console.WriteLine("ML-DSA-65 Schlüssel generiert:");
Console.WriteLine($" Public Key: {signatureKey.PublicKey.GetRawData().Length} Bytes");
Console.WriteLine($" OID: {signatureKey.PublicKey.Oid.Value}");
// Als PEM speichern
signatureKey.PublicKey.ToPemFile("signing.pub.pem");
signatureKey.ToEncryptedPemFile("signing.key.pem", "SecurePassword123!");
// Verschiedene Sicherheitsstufen
using var mlDsa44 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa44); // 128-bit
using var mlDsa65 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); // 192-bit (Standard)
using var mlDsa87 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa87); // 256-bit (Hochsicherheit)
----
===== Code-Beispiel: ML-KEM Verschlüsselungsschlüssel =====
using var ctx = PqCryptoContext.Initialize();
// ML-KEM-768 für Key Encapsulation (empfohlen)
using var kemKey = ctx.GenerateKeyPair(PqAlgorithm.MlKem768);
Console.WriteLine("ML-KEM-768 Schlüssel generiert:");
Console.WriteLine($" Public Key: {kemKey.PublicKey.GetRawData().Length} Bytes");
Console.WriteLine($" Verwendung: Key Encapsulation");
// Speichern
kemKey.PublicKey.ToPemFile("encryption.pub.pem");
kemKey.ToEncryptedPemFile("encryption.key.pem", "EncryptionPassword!");
----
===== Code-Beispiel: Hybrid-Schlüsselpaar =====
public class HybridKeyPair
{
public AsymmetricAlgorithm ClassicalKey { get; set; }
public PqKeyPair PqKey { get; set; }
public static HybridKeyPair Generate(
ClassicalAlgorithm classical,
PqAlgorithm pq)
{
using var ctx = PqCryptoContext.Initialize();
// Klassischer Schlüssel
var classicalKey = classical switch
{
ClassicalAlgorithm.RsA4096 => RSA.Create(4096),
ClassicalAlgorithm.EcdsaP384 => ECDsa.Create(ECCurve.NamedCurves.nistP384),
ClassicalAlgorithm.EcdhP384 => ECDiffieHellman.Create(ECCurve.NamedCurves.nistP384),
_ => throw new ArgumentException("Unbekannter Algorithmus")
};
// PQ-Schlüssel
var pqKey = ctx.GenerateKeyPair(pq);
return new HybridKeyPair
{
ClassicalKey = classicalKey,
PqKey = pqKey
};
}
public void SaveToFiles(string baseName, string password)
{
// Klassischer Schlüssel
if (ClassicalKey is RSA rsa)
{
var rsaPem = rsa.ExportRSAPrivateKeyPem();
File.WriteAllText($"{baseName}-classical.key.pem", rsaPem);
}
else if (ClassicalKey is ECDsa ecdsa)
{
var ecPem = ecdsa.ExportECPrivateKeyPem();
File.WriteAllText($"{baseName}-classical.key.pem", ecPem);
}
// PQ-Schlüssel
PqKey.ToEncryptedPemFile($"{baseName}-pq.key.pem", password);
PqKey.PublicKey.ToPemFile($"{baseName}-pq.pub.pem");
}
}
public enum ClassicalAlgorithm
{
RsA4096,
EcdsaP384,
EcdhP384
}
----
===== Batch-Generierung =====
public class KeyGenerationService
{
public Dictionary GenerateBatch(
int count,
PqAlgorithm algorithm,
string namePrefix)
{
using var ctx = PqCryptoContext.Initialize();
var keys = new Dictionary();
for (int i = 0; i < count; i++)
{
var name = $"{namePrefix}-{i:D4}";
var keyPair = ctx.GenerateKeyPair(algorithm);
keys[name] = keyPair;
Console.WriteLine($"Generiert: {name}");
}
return keys;
}
public void SaveBatch(
Dictionary keys,
string outputDir,
string password)
{
Directory.CreateDirectory(outputDir);
foreach (var (name, key) in keys)
{
key.PublicKey.ToPemFile(Path.Combine(outputDir, $"{name}.pub.pem"));
key.ToEncryptedPemFile(
Path.Combine(outputDir, $"{name}.key.pem"),
password
);
}
}
}
----
===== Entropie und Zufallszahlen =====
public class EntropySource
{
// System-CSPRNG (empfohlen)
public static byte[] GetSystemEntropy(int bytes)
{
return RandomNumberGenerator.GetBytes(bytes);
}
// Hardware RNG prüfen
public static bool IsHardwareRngAvailable()
{
try
{
// Intel RDRAND
return System.Runtime.Intrinsics.X86.Rdrand.IsSupported;
}
catch
{
return false;
}
}
// Zusätzliche Entropie einmischen (optional)
public static byte[] EnhancedEntropy(int bytes)
{
var systemEntropy = RandomNumberGenerator.GetBytes(bytes);
// Weitere Entropiequellen einmischen
var timestamp = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
var processId = BitConverter.GetBytes(Environment.ProcessId);
var gcMemory = BitConverter.GetBytes(GC.GetTotalMemory(false));
// Hash kombinieren
using var sha = SHA256.Create();
var combined = new byte[systemEntropy.Length + timestamp.Length + processId.Length + gcMemory.Length];
Buffer.BlockCopy(systemEntropy, 0, combined, 0, systemEntropy.Length);
Buffer.BlockCopy(timestamp, 0, combined, systemEntropy.Length, timestamp.Length);
Buffer.BlockCopy(processId, 0, combined, systemEntropy.Length + timestamp.Length, processId.Length);
Buffer.BlockCopy(gcMemory, 0, combined, systemEntropy.Length + timestamp.Length + processId.Length, gcMemory.Length);
var hashed = sha.ComputeHash(combined);
// Erweiterte Entropie für weitere Bytes
var result = new byte[bytes];
for (int i = 0; i < bytes; i += 32)
{
var blockSize = Math.Min(32, bytes - i);
Buffer.BlockCopy(hashed, 0, result, i, blockSize);
hashed = sha.ComputeHash(hashed);
}
return result;
}
}
----
===== Branchenspezifische Anforderungen =====
^ Branche ^ Min. Sicherheit ^ Empfohlener Algorithmus ^ HSM Pflicht? ^
| **Standard IT** | 128-bit | ML-DSA-65 / ML-KEM-768 | Nein |
| **Finanzsektor** | 192-bit | ML-DSA-65 / ML-KEM-768 | Ja |
| **Healthcare** | 192-bit | ML-DSA-65 / ML-KEM-768 | Empfohlen |
| **Government** | 256-bit | ML-DSA-87 / ML-KEM-1024 | Ja |
| **IoT** | 128-bit | ML-DSA-44 / ML-KEM-512 | Nein |
----
===== Verwandte Szenarien =====
^ Beziehung ^ Szenario ^ Beschreibung ^
| **Nächster Schritt** | [[.:speicherung|11.2 Schlüsselspeicherung]] | Sicheres Speichern |
| **Verwandt** | [[.:rotation|11.3 Schlüssel-Rotation]] | Regelmäßiger Austausch |
| **Verwandt** | [[de:int:pqcrypt:szenarien:csr:csr_server|2.1 Server-CSR]] | CSR erstellen |
----
<< [[.:start|← Schlüssel-Übersicht]] | [[de:int:pqcrypt:szenarien:start|↑ Szenarien]] | [[.:speicherung|11.2 Schlüsselspeicherung →]] >>
{{tag>szenario schluessel generierung ml-dsa ml-kem entropie}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//