Szenario 11.3: Schlüssel-Rotation
Kategorie: Schlüsselmanagement
Komplexität: ⭐⭐⭐⭐ (Hoch)
Voraussetzungen: Bestehende Schlüssel, Backup-Strategie
Geschätzte Zeit: 30-45 Minuten
Beschreibung
Dieses Szenario beschreibt die regelmäßige Rotation kryptographischer Schlüssel. Schlüssel-Rotation ist eine kritische Sicherheitsmaßnahme, die das Risiko einer Kompromittierung begrenzt.
Rotations-Gründe:
- Zeitbasiert - Maximale Schlüssel-Lebensdauer erreicht
- Nutzungsbasiert - Maximale Operationen/Datenvolumen
- Sicherheitsvorfall - Verdacht auf Kompromittierung
- Compliance - Regulatorische Anforderungen
- Algorithmus-Upgrade - Migration zu stärkeren Algorithmen
Workflow
flowchart TD
TRIGGER[Rotations-Trigger] --> CHECK{Rotation nötig?}
CHECK -->|Nein| WAIT[Warten]
CHECK -->|Ja| BACKUP[Alten Key sichern]
BACKUP --> GEN[Neuen Key generieren]
GEN --> MIGRATE[Systeme migrieren]
MIGRATE --> TEST[Funktionstest]
TEST --> OVERLAP{Überlappung OK?}
OVERLAP -->|Ja| RETIRE[Alten Key deaktivieren]
OVERLAP -->|Nein| ROLLBACK[Rollback]
RETIRE --> ARCHIVE[Archivieren/Löschen]
style GEN fill:#e8f5e9
style BACKUP fill:#fff3e0
Code-Beispiel: Automatische Rotation
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; public class KeyRotationService { private readonly IKeyStore _keyStore; private readonly TimeSpan _maxKeyAge = TimeSpan.FromDays(365); private readonly long _maxOperations = 1_000_000; public KeyRotationService(IKeyStore keyStore) { _keyStore = keyStore; } public async Task<RotationResult> CheckAndRotateAsync(string keyId) { var metadata = await _keyStore.GetMetadataAsync(keyId); // Rotations-Bedingungen prüfen var needsRotation = ShouldRotate(metadata); if (!needsRotation.Required) { return new RotationResult { KeyId = keyId, Rotated = false, Reason = "Keine Rotation erforderlich" }; } return await PerformRotationAsync(keyId, metadata, needsRotation.Reason); } private RotationCheck ShouldRotate(KeyMetadata metadata) { // 1. Zeitbasierte Rotation if (DateTime.UtcNow - metadata.CreatedAt > _maxKeyAge) { return new RotationCheck(true, "Maximales Alter erreicht"); } // 2. Nutzungsbasierte Rotation if (metadata.OperationCount > _maxOperations) { return new RotationCheck(true, "Maximale Operationen erreicht"); } // 3. Algorithmus-Upgrade (RSA → ML-DSA) if (metadata.Algorithm.StartsWith("RSA") && !metadata.Algorithm.Contains("ML-DSA")) { return new RotationCheck(true, "PQ-Migration erforderlich"); } return new RotationCheck(false, null); } private async Task<RotationResult> PerformRotationAsync( string keyId, KeyMetadata oldMetadata, string reason) { using var ctx = PqCryptoContext.Initialize(); // 1. Alten Schlüssel sichern await _keyStore.BackupAsync(keyId); // 2. Neuen Schlüssel generieren var newKeyId = $"{keyId}-{DateTime.UtcNow:yyyyMMdd}"; using var newKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); // 3. Neuen Schlüssel speichern await _keyStore.StoreAsync(newKeyId, newKey, new KeyMetadata { Algorithm = "ML-DSA-65", CreatedAt = DateTime.UtcNow, PreviousKeyId = keyId, RotationReason = reason }); // 4. Alten Schlüssel als "rotating" markieren await _keyStore.SetStatusAsync(keyId, KeyStatus.Rotating); return new RotationResult { KeyId = keyId, NewKeyId = newKeyId, Rotated = true, Reason = reason }; } }
Code-Beispiel: Überlappungsphase
public class OverlappingKeyManager { public async Task<byte[]> SignWithOverlap( byte[] data, string keyId, IKeyStore keyStore) { using var ctx = PqCryptoContext.Initialize(); // Aktuellen Schlüssel laden var currentKey = await keyStore.GetCurrentKeyAsync(keyId); // Mit aktuellem Schlüssel signieren var signature = ctx.SignData( data, currentKey, HashAlgorithmName.SHA256 ); return signature; } public async Task<bool> VerifyWithOverlap( byte[] data, byte[] signature, string keyId, IKeyStore keyStore) { using var ctx = PqCryptoContext.Initialize(); // Alle gültigen Schlüssel-Versionen holen var validKeys = await keyStore.GetValidKeysAsync(keyId); foreach (var key in validKeys) { try { if (ctx.VerifyData(data, signature, key.PublicKey, HashAlgorithmName.SHA256)) { return true; } } catch (CryptographicException) { // Falscher Schlüssel, nächsten versuchen continue; } } return false; } }
Code-Beispiel: HashiCorp Vault Rotation
public class VaultKeyRotation { private readonly IVaultClient _vault; public async Task RotateKeyInVault(string keyPath) { // 1. Aktuelle Version abrufen var current = await _vault.V1.Secrets.KeyValue.V2.ReadSecretAsync( path: keyPath, mountPoint: "secret" ); var currentVersion = current.Data.Metadata.Version; // 2. Neuen Schlüssel generieren using var ctx = PqCryptoContext.Initialize(); using var newKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); // 3. Als neue Version speichern (alte bleibt erhalten) var secretData = new Dictionary<string, object> { ["privateKey"] = Convert.ToBase64String(newKey.ExportPkcs8()), ["publicKey"] = Convert.ToBase64String(newKey.PublicKey.Export()), ["algorithm"] = "ML-DSA-65", ["rotatedAt"] = DateTime.UtcNow.ToString("O"), ["previousVersion"] = currentVersion }; await _vault.V1.Secrets.KeyValue.V2.WriteSecretAsync( path: keyPath, data: secretData, mountPoint: "secret" ); Console.WriteLine($"Schlüssel rotiert: {keyPath} v{currentVersion} → v{currentVersion + 1}"); } public async Task DestroyOldVersions(string keyPath, int keepVersions = 3) { // Alte Versionen löschen (Vault behält Metadaten) var metadata = await _vault.V1.Secrets.KeyValue.V2.ReadSecretMetadataAsync( path: keyPath, mountPoint: "secret" ); var currentVersion = metadata.Data.CurrentVersion; var versionsToDestroy = new List<int>(); for (int v = 1; v < currentVersion - keepVersions; v++) { versionsToDestroy.Add(v); } if (versionsToDestroy.Any()) { await _vault.V1.Secrets.KeyValue.V2.DestroySecretVersionsAsync( path: keyPath, versions: versionsToDestroy, mountPoint: "secret" ); Console.WriteLine($"Alte Versionen gelöscht: {string.Join(", ", versionsToDestroy)}"); } } }
Rotations-Richtlinien
| Schlüsseltyp | Max. Alter | Max. Operationen | Überlappung |
|---|---|---|---|
| Root-CA Key | 10-20 Jahre | N/A | 1 Jahr |
| Intermediate-CA Key | 3-5 Jahre | N/A | 90 Tage |
| TLS Server Key | 1 Jahr | 10M Handshakes | 7 Tage |
| Code Signing Key | 2 Jahre | 100K Signaturen | 30 Tage |
| Encryption Key | 1 Jahr | 100TB Daten | 30 Tage |
Branchenspezifische Rotations-Anforderungen
| Branche | Rotationszyklus | Anforderung | Besonderheit |
|---|---|---|---|
| Finanzsektor | 1 Jahr | PCI-DSS 3.6.4 | Audit-Trail Pflicht |
| Healthcare | 2 Jahre | HIPAA | Key Escrow |
| Energie/KRITIS | 3 Jahre | BSI KRITIS-VO | Wartungsfenster |
| Behörden | 2 Jahre | BSI TR-03116 | HSM-Pflicht |
Verwandte Szenarien
| Beziehung | Szenario | Beschreibung |
|---|---|---|
| Voraussetzung | 11.2 Schlüsselspeicherung | Sichere Aufbewahrung |
| Voraussetzung | 11.4 Schlüssel-Backup | Vor Rotation sichern |
| Nächster Schritt | 11.5 Schlüsselvernichtung | Alte Keys löschen |
| Verwandt | 4.2 Rekey | Zertifikat mit neuem Key |
« ← 11.2 Schlüsselspeicherung | ↑ Schlüssel-Übersicht | 11.4 Schlüssel-Backup → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: den 29.01.2026 um 15:13