Categoria: Gestire certificati
Complessità: Media
Prerequisiti: Certificati scaduti/revocati
Tempo stimato: 15-20 minuti
Questo scenario descrive l'archiviazione sicura di certificati e chiavi associate. L'archiviazione è necessaria per:
Importante: Le chiavi di crittografia devono essere archiviate se esistono ancora dati cifrati con esse. Le chiavi di firma NON dovrebbero essere archiviate (solo i certificati).
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Caricare certificati da archiviare var expiredCert = ctx.LoadCertificate("old-server.crt.pem"); var expiredKey = ctx.LoadPrivateKey("old-server.key.pem", "OldPassword!"); // Struttura archivio var archive = new CertificateArchive { Certificate = expiredCert, ArchivedAt = DateTime.UtcNow, OriginalPath = "old-server.crt.pem", Reason = ArchiveReason.Expired, RetentionUntil = DateTime.UtcNow.AddYears(10), Metadata = new Dictionary<string, string> { ["Subject"] = expiredCert.Subject, ["SerialNumber"] = expiredCert.SerialNumber, ["NotBefore"] = expiredCert.NotBefore.ToString("O"), ["NotAfter"] = expiredCert.NotAfter.ToString("O"), ["Thumbprint"] = expiredCert.Thumbprint, ["KeyUsage"] = GetKeyUsageString(expiredCert) } }; // Archiviare chiave solo per certificati di crittografia if (HasKeyEncipherment(expiredCert)) { // Salvare chiave cifrata var encryptedKey = ctx.EncryptPrivateKey( expiredKey, archivePassword: "ArchivePassword!SecureVault2024", algorithm: PbeAlgorithm.Aes256Cbc, prf: PbePrf.HmacSha256, iterations: 100000 ); archive.EncryptedPrivateKey = encryptedKey; } // Archiviare come JSON var archivePath = $"archive/{expiredCert.SerialNumber}.json"; File.WriteAllText(archivePath, JsonSerializer.Serialize(archive, new JsonSerializerOptions { WriteIndented = true })); // Log audit Console.WriteLine($"Archiviato: {expiredCert.Subject}"); Console.WriteLine($" Serial: {expiredCert.SerialNumber}"); Console.WriteLine($" Scadenza: {expiredCert.NotAfter:yyyy-MM-dd}"); Console.WriteLine($" Archivio: {archivePath}"); Console.WriteLine($" Conservazione fino a: {archive.RetentionUntil:yyyy-MM-dd}");
public class CertificateArchive { public string Version { get; } = "1.0"; public DateTime ArchivedAt { get; set; } public X509Certificate2 Certificate { get; set; } public byte[]? EncryptedPrivateKey { get; set; } // Solo per cert di crittografia public string OriginalPath { get; set; } public ArchiveReason Reason { get; set; } public DateTime RetentionUntil { get; set; } public Dictionary<string, string> Metadata { get; set; } public string? Notes { get; set; } } public enum ArchiveReason { Expired, Revoked, Superseded, KeyCompromise, CessationOfOperation, PolicyChange }
| Settore | Normativa | Periodo conservazione | Archiviare chiave? |
|---|---|---|---|
| Settore finanziario | GoBD | 10 anni | Si (crittografia) |
| Sanità | GDPR, PatArch | 30 anni | Si (dati pazienti) |
| Energia | EnWG, IT-SiG | 10 anni | Si (dati misurazione) |
| Pubblica Amministrazione | Leggi archivi | 30+ anni | Secondo tipo dati |
| IT standard | GDPR | 6 anni | No (solo certificato) |
// Directory archivio strutturata public class ArchiveDirectory { private readonly string _basePath; public ArchiveDirectory(string basePath) { _basePath = basePath; Directory.CreateDirectory(Path.Combine(basePath, "certificates")); Directory.CreateDirectory(Path.Combine(basePath, "keys")); Directory.CreateDirectory(Path.Combine(basePath, "metadata")); } public void Archive(CertificateArchive archive) { var serial = archive.Certificate.SerialNumber; var year = archive.Certificate.NotAfter.Year; // Certificato (PEM) var certPath = Path.Combine(_basePath, "certificates", $"{year}", $"{serial}.crt.pem"); Directory.CreateDirectory(Path.GetDirectoryName(certPath)!); archive.Certificate.ToPemFile(certPath); // Chiave (se presente) if (archive.EncryptedPrivateKey != null) { var keyPath = Path.Combine(_basePath, "keys", $"{year}", $"{serial}.key.enc"); Directory.CreateDirectory(Path.GetDirectoryName(keyPath)!); File.WriteAllBytes(keyPath, archive.EncryptedPrivateKey); } // Metadati var metaPath = Path.Combine(_basePath, "metadata", $"{year}", $"{serial}.json"); Directory.CreateDirectory(Path.GetDirectoryName(metaPath)!); File.WriteAllText(metaPath, JsonSerializer.Serialize(archive.Metadata)); } }
// Cercare certificati archiviati public IEnumerable<CertificateArchive> SearchArchive( string basePath, string? subjectFilter = null, DateTime? expiredAfter = null) { var metadataFiles = Directory.GetFiles( Path.Combine(basePath, "metadata"), "*.json", SearchOption.AllDirectories ); foreach (var file in metadataFiles) { var metadata = JsonSerializer.Deserialize<Dictionary<string, string>>( File.ReadAllText(file) ); if (subjectFilter != null && !metadata["Subject"].Contains(subjectFilter, StringComparison.OrdinalIgnoreCase)) continue; if (expiredAfter.HasValue && DateTime.Parse(metadata["NotAfter"]) < expiredAfter.Value) continue; var serial = Path.GetFileNameWithoutExtension(file); var year = Path.GetFileName(Path.GetDirectoryName(file)); yield return LoadArchive(basePath, year, serial); } }
| Relazione | Scenario | Descrizione |
|---|---|---|
| Prerequisito | 4.4 Backup | Salvare prima dell'archiviazione |
| Correlato | 11.5 Distruzione chiavi | Eliminare chiavi firma |
| Correlato | 6.4 Revocare | Prima dell'archiviazione |
« ← 4.2 Rekey | ↑ Panoramica gestione | 4.4 Backup → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional