~~NOTOC~~ ====== Szenario 4.4: Zertifikat- und Schlüssel-Backup ====== **Kategorie:** [[.:start|Zertifikate verwalten]] \\ **Komplexität:** ⭐⭐⭐⭐ (Hoch) \\ **Voraussetzungen:** Zertifikate und Schlüssel vorhanden \\ **Geschätzte Zeit:** 20-30 Minuten ---- ===== Beschreibung ===== Dieses Szenario beschreibt das **sichere Backup** von Zertifikaten, privaten Schlüsseln und CA-Infrastruktur. Ein korrektes Backup-Konzept ist kritisch für: * **Disaster Recovery** - Wiederherstellung nach Systemausfall * **Business Continuity** - Betriebsfortführung * **Compliance** - Nachweispflichten * **Key Escrow** - Schlüsselhinterlegung **KRITISCH:** Private Schlüssel sind das wertvollste Gut! Backups müssen: * Verschlüsselt sein * Offline gelagert werden * Zugriffsgeschützt sein * Regelmäßig getestet werden ---- ===== Workflow ===== flowchart TD START[Backup initiieren] --> COLLECT[Daten sammeln] COLLECT --> ENCRYPT[Verschlüsseln] ENCRYPT --> SIGN[Signieren] SIGN --> STORE1[Primär-Storage] SIGN --> STORE2[Sekundär-Storage] STORE1 --> VERIFY[Verifizieren] STORE2 --> VERIFY VERIFY --> LOG[Audit-Log] style ENCRYPT fill:#fff3e0 style STORE1 fill:#e8f5e9 style STORE2 fill:#e8f5e9 ---- ===== Code-Beispiel (C#) ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Backup-Konfiguration var backupConfig = new BackupConfiguration { EncryptionPassword = "BackupPassword!Secure2024", OutputPath = "backup/", Timestamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss"), IncludeChain = true }; // CA-Zertifikat und Schlüssel laden var caCert = ctx.LoadCertificate("root-ca.crt.pem"); var caKey = ctx.LoadPrivateKey("root-ca.key.pem", "CaPassword!"); // Verschlüsseltes PFX erstellen var pfxData = ctx.ExportToPfx( certificate: caCert, privateKey: caKey, chain: null, // Root hat keine Chain password: backupConfig.EncryptionPassword, friendlyName: $"Root-CA Backup {backupConfig.Timestamp}" ); // Backup-Datei mit Metadaten var backupPath = Path.Combine( backupConfig.OutputPath, $"root-ca-backup-{backupConfig.Timestamp}.pfx" ); Directory.CreateDirectory(backupConfig.OutputPath); File.WriteAllBytes(backupPath, pfxData); // Prüfsumme berechnen var checksum = ctx.ComputeSha256(pfxData); var checksumPath = backupPath + ".sha256"; File.WriteAllText(checksumPath, Convert.ToHexString(checksum)); // Metadaten speichern var metadata = new BackupMetadata { BackupDate = DateTime.UtcNow, Subject = caCert.Subject, SerialNumber = caCert.SerialNumber, NotAfter = caCert.NotAfter, Checksum = Convert.ToHexString(checksum), Algorithm = caCert.PublicKey.Oid.FriendlyName }; var metadataPath = backupPath + ".meta.json"; File.WriteAllText(metadataPath, JsonSerializer.Serialize(metadata, new JsonSerializerOptions { WriteIndented = true })); Console.WriteLine("Backup erstellt:"); Console.WriteLine($" Datei: {backupPath}"); Console.WriteLine($" SHA256: {metadata.Checksum}"); Console.WriteLine($" Größe: {new FileInfo(backupPath).Length:N0} Bytes"); ---- ===== Vollständiges CA-Backup ===== public class CaBackupManager { public void CreateFullBackup(string caDirectory, string backupPassword, string outputPath) { var timestamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss"); var backupDir = Path.Combine(outputPath, $"ca-backup-{timestamp}"); Directory.CreateDirectory(backupDir); using var ctx = PqCryptoContext.Initialize(); // 1. Root-CA BackupCertificateAndKey(ctx, caDirectory, "root-ca", backupDir, backupPassword); // 2. Alle Intermediate-CAs foreach (var intCaDir in Directory.GetDirectories(caDirectory, "intermediate-*")) { var name = Path.GetFileName(intCaDir); BackupCertificateAndKey(ctx, intCaDir, name, backupDir, backupPassword); } // 3. CRL-Dateien var crlDir = Path.Combine(backupDir, "crls"); Directory.CreateDirectory(crlDir); foreach (var crl in Directory.GetFiles(caDirectory, "*.crl", SearchOption.AllDirectories)) { File.Copy(crl, Path.Combine(crlDir, Path.GetFileName(crl))); } // 4. Konfigurationsdateien var configDir = Path.Combine(backupDir, "config"); Directory.CreateDirectory(configDir); foreach (var config in Directory.GetFiles(caDirectory, "*.json")) { File.Copy(config, Path.Combine(configDir, Path.GetFileName(config))); } // 5. Manifest erstellen CreateBackupManifest(backupDir, timestamp); Console.WriteLine($"Vollständiges CA-Backup erstellt: {backupDir}"); } private void BackupCertificateAndKey( PqCryptoContext ctx, string sourceDir, string name, string backupDir, string password) { var certPath = Path.Combine(sourceDir, $"{name}.crt.pem"); var keyPath = Path.Combine(sourceDir, $"{name}.key.pem"); if (!File.Exists(certPath)) return; var cert = ctx.LoadCertificate(certPath); // Zertifikat im Klartext (PEM) var certBackup = Path.Combine(backupDir, "certs", $"{name}.crt.pem"); Directory.CreateDirectory(Path.GetDirectoryName(certBackup)!); cert.ToPemFile(certBackup); // Schlüssel verschlüsselt (falls vorhanden) if (File.Exists(keyPath)) { // Schlüssel mit neuem Passwort verschlüsseln var key = ctx.LoadPrivateKey(keyPath, "OriginalPassword!"); // Anpassen! var keyBackup = Path.Combine(backupDir, "keys", $"{name}.key.pem.enc"); Directory.CreateDirectory(Path.GetDirectoryName(keyBackup)!); key.ToEncryptedPemFile(keyBackup, password); } } private void CreateBackupManifest(string backupDir, string timestamp) { var manifest = new { Version = "1.0", Timestamp = timestamp, CreatedAt = DateTime.UtcNow, Contents = new { Certificates = Directory.GetFiles(Path.Combine(backupDir, "certs"), "*.pem").Length, Keys = Directory.GetFiles(Path.Combine(backupDir, "keys"), "*.enc").Length, CRLs = Directory.GetFiles(Path.Combine(backupDir, "crls"), "*.crl").Length, Configs = Directory.GetFiles(Path.Combine(backupDir, "config"), "*.json").Length } }; var manifestPath = Path.Combine(backupDir, "MANIFEST.json"); File.WriteAllText(manifestPath, JsonSerializer.Serialize(manifest, new JsonSerializerOptions { WriteIndented = true })); } } ---- ===== Backup-Verifizierung ===== public bool VerifyBackup(string backupPath, string password) { using var ctx = PqCryptoContext.Initialize(); // 1. Prüfsumme verifizieren var expectedChecksum = File.ReadAllText(backupPath + ".sha256"); var actualData = File.ReadAllBytes(backupPath); var actualChecksum = Convert.ToHexString(ctx.ComputeSha256(actualData)); if (expectedChecksum != actualChecksum) { Console.WriteLine("FEHLER: Prüfsumme stimmt nicht!"); return false; } // 2. PFX laden (testet Passwort und Integrität) try { var (cert, key) = ctx.ImportFromPfx(actualData, password); Console.WriteLine($"Backup OK: {cert.Subject}"); Console.WriteLine($" Gültig bis: {cert.NotAfter:yyyy-MM-dd}"); Console.WriteLine($" Schlüssel: {(key != null ? "Vorhanden" : "Fehlt")}"); return true; } catch (CryptographicException ex) { Console.WriteLine($"FEHLER: {ex.Message}"); return false; } } ---- ===== Branchenspezifische Backup-Anforderungen ===== ^ Branche ^ Vorschrift ^ Backup-Frequenz ^ Aufbewahrung ^ Besonderheit ^ | **Finanzsektor** | MaRisk | Täglich | 10 Jahre | Georedundanz Pflicht | | **Healthcare** | DSGVO | Täglich | 30 Jahre | Air-Gap Storage | | **Energie** | KRITIS-VO | Wöchentlich | 10 Jahre | Offline-Medien | | **Automotive** | UNECE R155 | Monatlich | Fahrzeug-Lifetime | OTA-Recovery | ---- ===== Backup-Strategie 3-2-1 ===== **3-2-1 Regel:** * **3** Kopien der Daten * **2** verschiedene Medientypen * **1** Kopie Off-Site | Kopie | Medium | Ort | Zweck | |-------|--------|-----|-------| | 1 | Server-Storage | Rechenzentrum | Operativ | | 2 | Tape/NAS | Gebäude B | Disaster Recovery | | 3 | Cloud (verschlüsselt) | Anderer Standort | Georedundanz | ---- ===== Verwandte Szenarien ===== ^ Beziehung ^ Szenario ^ Beschreibung ^ | **Nächster Schritt** | [[.:archivierung|4.3 Archivierung]] | Langzeit-Aufbewahrung | | **Verwandt** | [[de:int:pqcrypt:szenarien:schluessel:speicherung|11.2 Schlüsselspeicherung]] | Key Storage | | **Verwandt** | [[de:int:pqcrypt:szenarien:importexport:pfx_export|12.2 PFX-Export]] | Export-Format | ---- << [[.:archivierung|← 4.3 Archivierung]] | [[.:start|↑ Verwaltung-Übersicht]] | [[de:int:pqcrypt:szenarien:start|→ Alle Szenarien]] >> {{tag>szenario verwaltung backup disaster-recovery pfx}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//