~~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//