~~NOTOC~~ ====== Scenarij 11.5: Uništavanje ključeva ====== **Kategorija:** [[.:start|Upravljanje ključevima]] \\ **Složenost:** ⭐⭐⭐⭐ (Visoka) \\ **Preduvjeti:** Ključ više nije potreban, sigurnosne kopije provjerene \\ **Procijenjeno vrijeme:** 20-30 minuta ---- ===== Opis ===== Ovaj scenarij opisuje **sigurno i neopozivo uništavanje kriptografskih ključeva**. Pravilno uništavanje ključeva je posljednji korak u životnom ciklusu ključa i kritično je za sigurnost. **Razlozi za uništavanje:** * **Kraj životnog ciklusa** - Životni ciklus ključa završen * **Kompromitacija** - Ključ je možda poznat * **Usklađenost** - Istekli rokovi čuvanja * **Isključivanje** - Sustav se gasi * **Migracija algoritma** - Stari ključevi nakon PQ prijelaza **UPOZORENJE:** Uništavanje ključa je neopozivo! Provjerite: * Svi šifrirani podaci su dešifrirani ili više nisu potrebni * Svi potpisi su validirani ili više nisu relevantni * Sigurnosne kopije su također uništene ---- ===== Tijek rada ===== flowchart TD INIT[Pokretanje uništavanja] --> CHECK{Provjere} CHECK --> DEP[Provjera ovisnosti] DEP --> BAK[Lociranje sigurnosnih kopija] BAK --> APPROVE{Odobrenje?} APPROVE -->|Ne| ABORT[Prekid] APPROVE -->|Da| DESTROY[Prepisivanje ključa] DESTROY --> BACKUP_DEL[Uništavanje sigurnosnih kopija] BACKUP_DEL --> HSM_DEL[Brisanje HSM ključeva] HSM_DEL --> LOG[Audit-Log] LOG --> CERT[Potvrda] style DESTROY fill:#ffebee style BACKUP_DEL fill:#ffebee style HSM_DEL fill:#ffebee ---- ===== Primjer koda: Sigurno brisanje memorije ===== using System.Security.Cryptography; using System.Runtime.InteropServices; public class SecureKeyDestruction { public void DestroyKeyInMemory(byte[] keyMaterial) { if (keyMaterial == null || keyMaterial.Length == 0) return; // 1. Prepisivanje nasumičnim podacima RandomNumberGenerator.Fill(keyMaterial); // 2. Prepisivanje nulama Array.Clear(keyMaterial, 0, keyMaterial.Length); // 3. Ponovno prepisivanje nasumičnim podacima RandomNumberGenerator.Fill(keyMaterial); // 4. Konačno prepisivanje nulama CryptographicOperations.ZeroMemory(keyMaterial); Console.WriteLine($"Memorija obrisana: {keyMaterial.Length} bajta"); } public void DestroyKeyOnDisk(string keyFilePath) { if (!File.Exists(keyFilePath)) { Console.WriteLine($"Datoteka nije pronađena: {keyFilePath}"); return; } var fileInfo = new FileInfo(keyFilePath); var fileLength = fileInfo.Length; // Višestruko prepisivanje (DoD 5220.22-M standard) using (var fs = new FileStream(keyFilePath, FileMode.Open, FileAccess.Write)) { var buffer = new byte[4096]; // Prolaz 1: Prepisivanje s 0x00 OverwriteFile(fs, fileLength, 0x00); // Prolaz 2: Prepisivanje s 0xFF OverwriteFile(fs, fileLength, 0xFF); // Prolaz 3: Prepisivanje nasumičnim podacima OverwriteFileRandom(fs, fileLength); // Prolaz 4: Ponovno s 0x00 OverwriteFile(fs, fileLength, 0x00); fs.Flush(); } // Preimenovanje datoteke (prikrivanje metapodataka) var randomName = Path.Combine( Path.GetDirectoryName(keyFilePath), Guid.NewGuid().ToString() ); File.Move(keyFilePath, randomName); // Brisanje datoteke File.Delete(randomName); Console.WriteLine($"Datoteka ključa sigurno obrisana: {keyFilePath}"); } private void OverwriteFile(FileStream fs, long length, byte value) { fs.Seek(0, SeekOrigin.Begin); var buffer = new byte[4096]; Array.Fill(buffer, value); long remaining = length; while (remaining > 0) { int toWrite = (int)Math.Min(remaining, buffer.Length); fs.Write(buffer, 0, toWrite); remaining -= toWrite; } } private void OverwriteFileRandom(FileStream fs, long length) { fs.Seek(0, SeekOrigin.Begin); var buffer = new byte[4096]; long remaining = length; while (remaining > 0) { RandomNumberGenerator.Fill(buffer); int toWrite = (int)Math.Min(remaining, buffer.Length); fs.Write(buffer, 0, toWrite); remaining -= toWrite; } } } ---- ===== Primjer koda: Potpuno uništavanje s protokolom ===== public class KeyDestructionService { private readonly ILogger _logger; private readonly IAuditLog _auditLog; public async Task DestroyKeyAsync( string keyId, string reason, string authorizedBy, DestructionOptions options = null) { options ??= DestructionOptions.Default; var certificate = new DestructionCertificate { KeyId = keyId, DestructionId = Guid.NewGuid().ToString(), InitiatedAt = DateTime.UtcNow, Reason = reason, AuthorizedBy = authorizedBy }; try { // 1. Provjera ovisnosti await ValidateDestructionAsync(keyId, certificate); // 2. Uništavanje aktivnog ključa await DestroyPrimaryKeyAsync(keyId, certificate); // 3. Uništavanje svih sigurnosnih kopija if (options.DestroyBackups) { await DestroyBackupsAsync(keyId, certificate); } // 4. Uništavanje HSM ključeva if (options.DestroyHsmKeys) { await DestroyHsmKeyAsync(keyId, certificate); } // 5. Kreiranje Audit-Loga certificate.CompletedAt = DateTime.UtcNow; certificate.Status = DestructionStatus.Completed; await _auditLog.LogAsync(new AuditEntry { Action = "KEY_DESTRUCTION", KeyId = keyId, Details = certificate, Timestamp = DateTime.UtcNow }); _logger.LogInformation( "Ključ {KeyId} uspješno uništen. Potvrda: {DestructionId}", keyId, certificate.DestructionId); return certificate; } catch (Exception ex) { certificate.Status = DestructionStatus.Failed; certificate.Error = ex.Message; _logger.LogError(ex, "Uništavanje ključa neuspješno: {KeyId}", keyId); throw; } } private async Task ValidateDestructionAsync(string keyId, DestructionCertificate cert) { // Provjera postoje li još aktivni certifikati var activeCerts = await _certStore.FindByKeyIdAsync(keyId); if (activeCerts.Any(c => c.NotAfter > DateTime.UtcNow)) { throw new InvalidOperationException( $"Ključ {keyId} još koristi {activeCerts.Count} aktivnih certifikata"); } cert.ValidationsPassed.Add("Nema aktivnih certifikata"); // Provjera je li rok čuvanja istekao var metadata = await _keyStore.GetMetadataAsync(keyId); if (metadata.RetentionUntil > DateTime.UtcNow) { throw new InvalidOperationException( $"Rok čuvanja traje do {metadata.RetentionUntil:d}"); } cert.ValidationsPassed.Add("Rok čuvanja istekao"); } private async Task DestroyPrimaryKeyAsync(string keyId, DestructionCertificate cert) { var keyPath = await _keyStore.GetPathAsync(keyId); var destruction = new SecureKeyDestruction(); // Učitavanje ključa i spremanje otiska za potvrdu var keyData = await File.ReadAllBytesAsync(keyPath); cert.KeyFingerprint = Convert.ToHexString(SHA256.HashData(keyData)).Substring(0, 32); // Sigurno uništavanje destruction.DestroyKeyOnDisk(keyPath); destruction.DestroyKeyInMemory(keyData); cert.PrimaryKeyDestroyed = true; cert.DestroyedLocations.Add(keyPath); } private async Task DestroyBackupsAsync(string keyId, DestructionCertificate cert) { var backupLocations = await _backupStore.FindBackupsAsync(keyId); var destruction = new SecureKeyDestruction(); foreach (var backupPath in backupLocations) { destruction.DestroyKeyOnDisk(backupPath); cert.DestroyedLocations.Add(backupPath); } cert.BackupsDestroyed = backupLocations.Count; } private async Task DestroyHsmKeyAsync(string keyId, DestructionCertificate cert) { // Brisanje HSM ključa (PKCS#11) using var pkcs11 = new Pkcs11Library(_hsmConfig.LibraryPath); var slot = pkcs11.GetSlotList(SlotsType.WithTokenPresent).First(); using var session = slot.OpenSession(SessionType.ReadWrite); session.Login(CKU.CKU_USER, _hsmConfig.UserPin); try { var key = session.FindAllObjects(new List { new ObjectAttribute(CKA.CKA_LABEL, keyId) }).FirstOrDefault(); if (key != null) { session.DestroyObject(key); cert.HsmKeyDestroyed = true; cert.DestroyedLocations.Add($"HSM:{keyId}"); } } finally { session.Logout(); } } } public class DestructionCertificate { public string DestructionId { get; set; } public string KeyId { get; set; } public string KeyFingerprint { get; set; } public DateTime InitiatedAt { get; set; } public DateTime? CompletedAt { get; set; } public string Reason { get; set; } public string AuthorizedBy { get; set; } public DestructionStatus Status { get; set; } public List ValidationsPassed { get; set; } = new(); public bool PrimaryKeyDestroyed { get; set; } public int BackupsDestroyed { get; set; } public bool HsmKeyDestroyed { get; set; } public List DestroyedLocations { get; set; } = new(); public string Error { get; set; } } public enum DestructionStatus { InProgress, Completed, Failed } ---- ===== Primjer koda: Uništavanje DPAPI ključa ===== public class DpapiKeyDestruction { public void DestroyDpapiKey(string keyId) { var keyPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WvdS", "Keys", $"{keyId}.dpapi" ); if (!File.Exists(keyPath)) { Console.WriteLine($"DPAPI ključ nije pronađen: {keyId}"); return; } var destruction = new SecureKeyDestruction(); // Sigurno brisanje datoteke destruction.DestroyKeyOnDisk(keyPath); // Također uklanjanje eventualnih unosa u registru try { using var key = Registry.CurrentUser.OpenSubKey( @"Software\WvdS\CryptoKeys", writable: true); key?.DeleteValue(keyId, throwOnMissingValue: false); } catch (Exception ex) { Console.WriteLine($"Čišćenje registra neuspješno: {ex.Message}"); } Console.WriteLine($"DPAPI ključ uništen: {keyId}"); } } ---- ===== Standardi uništavanja ===== ^ Standard ^ Prepisivanja ^ Uzorak ^ Primjena ^ | **DoD 5220.22-M** | 3 | 0x00, 0xFF, Random | Vojska SAD-a | | **NIST SP 800-88** | 1-3 | Ovisno o tipu medija | Vlada SAD-a | | **BSI-TL 03423** | 3 | Random, 0x00, 0xFF | Njemačke vlasti | | **Gutmann** | 35 | Različiti uzorci | Paranoidan | Za SSD-ove i Flash memoriju: Sigurno brisanje zahtijeva posebne firmware naredbe (TRIM, Secure Erase). Softversko prepisivanje nije pouzdano! ---- ===== Zahtjevi za uništavanje specifični za industriju ===== ^ Industrija ^ Zahtjev ^ Svjedoci ^ Dokumentacija ^ | **Financijski sektor** | PCI-DSS 3.6.6 | 2 osobe | Protokol uništavanja | | **Zdravstvo** | HIPAA | 1 svjedok | Audit-Log | | **Vlada** | VS-NfD | Povjerenik za sigurnost | Potvrda o uništavanju | | **KRITIS** | BSI | 2 osobe | Certifikat + Protokol | ---- ===== Povezani scenariji ===== ^ Povezanost ^ Scenarij ^ Opis ^ | **Preduvjet** | [[.:backup|11.4 Sigurnosna kopija ključeva]] | Identifikacija svih kopija | | **Preduvjet** | [[.:rotation|11.3 Rotacija ključeva]] | Novi ključevi prije uništavanja | | **Povezano** | [[hr:int:pqcrypt:szenarien:widerruf:zertifikat_widerrufen|6.4 Opoziv certifikata]] | Opoziv prije uništavanja | | **Povezano** | [[hr:int:pqcrypt:szenarien:verwaltung:archivierung|4.3 Arhiviranje]] | Alternativa: Arhiviranje umjesto uništavanja | ---- << [[.:backup|← 11.4 Sigurnosna kopija ključeva]] | [[.:start|↑ Pregled ključeva]] | [[hr:int:pqcrypt:szenarien:start|→ Svi scenariji]] >> {{tag>scenarij ključ uništavanje sigurnost usklađenost audit}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//