~~NOTOC~~
====== Scenario 4.4: Backup certificati e chiavi ======
**Categoria:** [[.:start|Gestire certificati]] \\
**Complessità:** Alta \\
**Prerequisiti:** Certificati e chiavi esistenti \\
**Tempo stimato:** 20-30 minuti
----
===== Descrizione =====
Questo scenario descrive il **backup sicuro** di certificati, chiavi private e infrastruttura CA. Un concetto di backup corretto è critico per:
* **Disaster Recovery** - Ripristino dopo guasto di sistema
* **Business Continuity** - Continuità operativa
* **Compliance** - Obblighi di documentazione
* **Key Escrow** - Deposito delle chiavi
**CRITICO:** Le chiavi private sono il bene più prezioso! I backup devono:
* Essere cifrati
* Essere conservati offline
* Essere protetti da accesso
* Essere testati regolarmente
----
===== Workflow =====
flowchart TD
START[Avviare backup] --> COLLECT[Raccogliere dati]
COLLECT --> ENCRYPT[Cifrare]
ENCRYPT --> SIGN[Firmare]
SIGN --> STORE1[Storage primario]
SIGN --> STORE2[Storage secondario]
STORE1 --> VERIFY[Verificare]
STORE2 --> VERIFY
VERIFY --> LOG[Log audit]
style ENCRYPT fill:#fff3e0
style STORE1 fill:#e8f5e9
style STORE2 fill:#e8f5e9
----
===== Esempio codice (C#) =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using var ctx = PqCryptoContext.Initialize();
// Configurazione backup
var backupConfig = new BackupConfiguration
{
EncryptionPassword = "BackupPassword!Secure2024",
OutputPath = "backup/",
Timestamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss"),
IncludeChain = true
};
// Caricare certificato e chiave CA
var caCert = ctx.LoadCertificate("root-ca.crt.pem");
var caKey = ctx.LoadPrivateKey("root-ca.key.pem", "CaPassword!");
// Creare PFX cifrato
var pfxData = ctx.ExportToPfx(
certificate: caCert,
privateKey: caKey,
chain: null, // Root non ha chain
password: backupConfig.EncryptionPassword,
friendlyName: $"Root-CA Backup {backupConfig.Timestamp}"
);
// File backup con metadati
var backupPath = Path.Combine(
backupConfig.OutputPath,
$"root-ca-backup-{backupConfig.Timestamp}.pfx"
);
Directory.CreateDirectory(backupConfig.OutputPath);
File.WriteAllBytes(backupPath, pfxData);
// Calcolare checksum
var checksum = ctx.ComputeSha256(pfxData);
var checksumPath = backupPath + ".sha256";
File.WriteAllText(checksumPath, Convert.ToHexString(checksum));
// Salvare metadati
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 creato:");
Console.WriteLine($" File: {backupPath}");
Console.WriteLine($" SHA256: {metadata.Checksum}");
Console.WriteLine($" Dimensione: {new FileInfo(backupPath).Length:N0} Bytes");
----
===== Backup completo CA =====
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. Tutte le Intermediate-CA
foreach (var intCaDir in Directory.GetDirectories(caDirectory, "intermediate-*"))
{
var name = Path.GetFileName(intCaDir);
BackupCertificateAndKey(ctx, intCaDir, name, backupDir, backupPassword);
}
// 3. File CRL
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. File di configurazione
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. Creare manifest
CreateBackupManifest(backupDir, timestamp);
Console.WriteLine($"Backup completo CA creato: {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);
// Certificato in chiaro (PEM)
var certBackup = Path.Combine(backupDir, "certs", $"{name}.crt.pem");
Directory.CreateDirectory(Path.GetDirectoryName(certBackup)!);
cert.ToPemFile(certBackup);
// Chiave cifrata (se presente)
if (File.Exists(keyPath))
{
// Cifrare chiave con nuova password
var key = ctx.LoadPrivateKey(keyPath, "OriginalPassword!"); // Adattare!
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
}));
}
}
----
===== Verifica backup =====
public bool VerifyBackup(string backupPath, string password)
{
using var ctx = PqCryptoContext.Initialize();
// 1. Verificare checksum
var expectedChecksum = File.ReadAllText(backupPath + ".sha256");
var actualData = File.ReadAllBytes(backupPath);
var actualChecksum = Convert.ToHexString(ctx.ComputeSha256(actualData));
if (expectedChecksum != actualChecksum)
{
Console.WriteLine("ERRORE: Checksum non corrispondente!");
return false;
}
// 2. Caricare PFX (testa password e integrità)
try
{
var (cert, key) = ctx.ImportFromPfx(actualData, password);
Console.WriteLine($"Backup OK: {cert.Subject}");
Console.WriteLine($" Valido fino a: {cert.NotAfter:yyyy-MM-dd}");
Console.WriteLine($" Chiave: {(key != null ? "Presente" : "Mancante")}");
return true;
}
catch (CryptographicException ex)
{
Console.WriteLine($"ERRORE: {ex.Message}");
return false;
}
}
----
===== Requisiti backup specifici per settore =====
^ Settore ^ Normativa ^ Frequenza backup ^ Conservazione ^ Particolarità ^
| **Settore finanziario** | MaRisk | Giornaliera | 10 anni | Georidondanza obbligatoria |
| **Sanità** | GDPR | Giornaliera | 30 anni | Storage air-gap |
| **Energia** | KRITIS-VO | Settimanale | 10 anni | Supporti offline |
| **Automotive** | UNECE R155 | Mensile | Vita veicolo | Recovery OTA |
----
===== Strategia backup 3-2-1 =====
**Regola 3-2-1:**
* **3** copie dei dati
* **2** tipi di supporti diversi
* **1** copia off-site
| Copia | Supporto | Luogo | Scopo |
|-------|----------|-------|-------|
| 1 | Server-Storage | Data center | Operativo |
| 2 | Tape/NAS | Edificio B | Disaster Recovery |
| 3 | Cloud (cifrato) | Altra sede | Georidondanza |
----
===== Scenari correlati =====
^ Relazione ^ Scenario ^ Descrizione ^
| **Passo successivo** | [[.:archivierung|4.3 Archiviazione]] | Conservazione a lungo termine |
| **Correlato** | [[it:int:pqcrypt:szenarien:schluessel:speicherung|11.2 Storage chiavi]] | Key Storage |
| **Correlato** | [[it:int:pqcrypt:szenarien:importexport:pfx_export|12.2 Export PFX]] | Formato export |
----
<< [[.:archivierung|← 4.3 Archiviazione]] | [[.:start|↑ Panoramica gestione]] | [[it:int:pqcrypt:szenarien:start|→ Tutti gli scenari]] >>
{{tag>scenario gestione backup disaster-recovery pfx}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//