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