Scenario 11.5: Key Destruction

Category: Key Management
Complexity: ⭐⭐⭐⭐ (High)
Prerequisites: Key no longer needed, backups verified
Estimated Time: 20-30 Minutes


Description

This scenario describes the secure and irreversible destruction of cryptographic keys. Proper key destruction is the final step in the key lifecycle and critical for security.

Destruction Reasons:

  • End of Life - Key lifecycle ended
  • Compromise - Key possibly known
  • Compliance - Retention periods expired
  • Decommissioning - System being retired
  • Algorithm Migration - Old keys after PQ transition

WARNING: Key destruction is irreversible! Ensure:

  • All encrypted data is decrypted or no longer needed
  • All signatures are validated or no longer relevant
  • Backups have also been destroyed

Workflow

flowchart TD INIT[Initiate destruction] --> CHECK{Checks} CHECK --> DEP[Check dependencies] DEP --> BAK[Locate backups] BAK --> APPROVE{Approval?} APPROVE -->|No| ABORT[Abort] APPROVE -->|Yes| DESTROY[Overwrite key] DESTROY --> BACKUP_DEL[Destroy backups] BACKUP_DEL --> HSM_DEL[Delete HSM keys] HSM_DEL --> LOG[Audit log] LOG --> CERT[Certificate] style DESTROY fill:#ffebee style BACKUP_DEL fill:#ffebee style HSM_DEL fill:#ffebee


Code Example: Secure Memory Deletion

using System.Security.Cryptography;
using System.Runtime.InteropServices;
 
public class SecureKeyDestruction
{
    public void DestroyKeyInMemory(byte[] keyMaterial)
    {
        if (keyMaterial == null || keyMaterial.Length == 0)
            return;
 
        // 1. Overwrite with random data
        RandomNumberGenerator.Fill(keyMaterial);
 
        // 2. Overwrite with zeros
        Array.Clear(keyMaterial, 0, keyMaterial.Length);
 
        // 3. Overwrite again with random data
        RandomNumberGenerator.Fill(keyMaterial);
 
        // 4. Final overwrite with zeros
        CryptographicOperations.ZeroMemory(keyMaterial);
 
        Console.WriteLine($"Memory cleared: {keyMaterial.Length} bytes");
    }
 
    public void DestroyKeyOnDisk(string keyFilePath)
    {
        if (!File.Exists(keyFilePath))
        {
            Console.WriteLine($"File not found: {keyFilePath}");
            return;
        }
 
        var fileInfo = new FileInfo(keyFilePath);
        var fileLength = fileInfo.Length;
 
        // Multiple overwrites (DoD 5220.22-M Standard)
        using (var fs = new FileStream(keyFilePath, FileMode.Open, FileAccess.Write))
        {
            var buffer = new byte[4096];
 
            // Pass 1: Overwrite with 0x00
            OverwriteFile(fs, fileLength, 0x00);
 
            // Pass 2: Overwrite with 0xFF
            OverwriteFile(fs, fileLength, 0xFF);
 
            // Pass 3: Overwrite with random data
            OverwriteFileRandom(fs, fileLength);
 
            // Pass 4: Again with 0x00
            OverwriteFile(fs, fileLength, 0x00);
 
            fs.Flush();
        }
 
        // Rename file (obscure metadata)
        var randomName = Path.Combine(
            Path.GetDirectoryName(keyFilePath),
            Guid.NewGuid().ToString()
        );
        File.Move(keyFilePath, randomName);
 
        // Delete file
        File.Delete(randomName);
 
        Console.WriteLine($"Key file securely deleted: {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;
        }
    }
}

Code Example: Complete Destruction with Protocol

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. Check dependencies
            await ValidateDestructionAsync(keyId, certificate);
 
            // 2. Destroy active key
            await DestroyPrimaryKeyAsync(keyId, certificate);
 
            // 3. Destroy all backups
            if (options.DestroyBackups)
            {
                await DestroyBackupsAsync(keyId, certificate);
            }
 
            // 4. Destroy HSM keys
            if (options.DestroyHsmKeys)
            {
                await DestroyHsmKeyAsync(keyId, certificate);
            }
 
            // 5. Create audit log
            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(
                "Key {KeyId} successfully destroyed. Certificate: {DestructionId}",
                keyId, certificate.DestructionId);
 
            return certificate;
        }
        catch (Exception ex)
        {
            certificate.Status = DestructionStatus.Failed;
            certificate.Error = ex.Message;
 
            _logger.LogError(ex, "Key destruction failed: {KeyId}", keyId);
            throw;
        }
    }
 
    private async Task ValidateDestructionAsync(string keyId, DestructionCertificate cert)
    {
        // Check if active certificates still exist
        var activeCerts = await _certStore.FindByKeyIdAsync(keyId);
        if (activeCerts.Any(c => c.NotAfter > DateTime.UtcNow))
        {
            throw new InvalidOperationException(
                $"Key {keyId} is still used by {activeCerts.Count} active certificates");
        }
 
        cert.ValidationsPassed.Add("No active certificates");
 
        // Check if retention period expired
        var metadata = await _keyStore.GetMetadataAsync(keyId);
        if (metadata.RetentionUntil > DateTime.UtcNow)
        {
            throw new InvalidOperationException(
                $"Retention period runs until {metadata.RetentionUntil:d}");
        }
 
        cert.ValidationsPassed.Add("Retention period expired");
    }
}
 
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
}

Destruction Standards

Standard Overwrites Pattern Application
DoD 5220.22-M 3 0x00, 0xFF, Random US Military
NIST SP 800-88 1-3 Depends on media type US Government
BSI-TL 03423 3 Random, 0x00, 0xFF German Authorities
Gutmann 35 Various patterns Paranoid

For SSDs and flash storage: Secure deletion requires special firmware commands (TRIM, Secure Erase). Software overwriting is not reliable!


Industry-Specific Destruction Requirements

Industry Requirement Witnesses Documentation
Financial Sector PCI-DSS 3.6.6 2 persons Destruction protocol
Healthcare HIPAA 1 witness Audit log
Government VS-NfD Security Officer Destruction certificate
KRITIS BSI 2 persons Certificate + Protocol

Relationship Scenario Description
Prerequisite 11.4 Key Backup Identify all backups
Prerequisite 11.3 Key Rotation New keys before destruction
Related 6.4 Revoke Certificate Revoke before destruction
Related 4.3 Archival Alternative: Archive instead of destroy

« ← 11.4 Key Backup | ↑ Key Overview | → All Scenarios »


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

Zuletzt geändert: on 2026/01/30 at 06:43 AM