Scenarij 11.5: Uništavanje ključeva

Kategorija: 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<DestructionCertificate> 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<ObjectAttribute>
            {
                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<string> ValidationsPassed { get; set; } = new();
    public bool PrimaryKeyDestroyed { get; set; }
    public int BackupsDestroyed { get; set; }
    public bool HsmKeyDestroyed { get; set; }
    public List<string> 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 11.4 Sigurnosna kopija ključeva Identifikacija svih kopija
Preduvjet 11.3 Rotacija ključeva Novi ključevi prije uništavanja
Povezano 6.4 Opoziv certifikata Opoziv prije uništavanja
Povezano 4.3 Arhiviranje Alternativa: Arhiviranje umjesto uništavanja

« ← 11.4 Sigurnosna kopija ključeva | ↑ Pregled ključeva | → Svi scenariji »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: 30.01.2026. u 00:31