Scenario 11.4: Key Backup

Category: Key Management
Complexity: ⭐⭐⭐⭐ (High)
Prerequisites: Generated keys, backup infrastructure
Estimated Time: 25-35 Minutes


Description

This scenario describes the secure backup of cryptographic keys. A well-designed backup concept is essential for business continuity and disaster recovery.

Backup Strategies:

  • Encrypted Backup - AES-256 or PQ-hybrid
  • Key Splitting - Shamir's Secret Sharing
  • Geographic Distribution - Multiple locations
  • Offline Backup - Air-gapped systems
  • HSM Backup - Hardware-based

Workflow

flowchart TD KEY[Private Key] --> ENCRYPT[Encrypt] ENCRYPT --> SPLIT{Splitting?} SPLIT -->|Yes| SHAMIR[Shamir Split n-of-m] SPLIT -->|No| SINGLE[Single Backup] SHAMIR --> DIST[Distribute] SINGLE --> STORE[Store] DIST --> LOC1[Location 1] DIST --> LOC2[Location 2] DIST --> LOC3[Location 3] STORE --> OFFSITE[Offsite Storage] LOC1 --> VERIFY[Restore Test] LOC2 --> VERIFY LOC3 --> VERIFY OFFSITE --> VERIFY style ENCRYPT fill:#fff3e0 style VERIFY fill:#e8f5e9


Code Example: Encrypted Backup

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography;
 
public class KeyBackupService
{
    public void CreateEncryptedBackup(
        AsymmetricAlgorithm privateKey,
        string backupPath,
        string backupPassword,
        BackupOptions options = null)
    {
        options ??= BackupOptions.Default;
        using var ctx = PqCryptoContext.Initialize();
 
        // 1. Export private key as PKCS#8
        byte[] pkcs8 = privateKey switch
        {
            RSA rsa => rsa.ExportPkcs8PrivateKey(),
            ECDsa ecdsa => ecdsa.ExportPkcs8PrivateKey(),
            _ => ctx.ExportPrivateKey(privateKey)
        };
 
        // 2. Derive Key Encryption Key (KEK)
        var salt = RandomNumberGenerator.GetBytes(32);
        var kek = ctx.DeriveKey(
            backupPassword,
            salt,
            outputLength: 32,
            algorithm: KeyDerivationAlgorithm.Argon2id,
            iterations: 4,
            memoryKiB: 65536,
            parallelism: 4
        );
 
        // 3. Encrypt with AES-256-GCM
        var nonce = RandomNumberGenerator.GetBytes(12);
        var ciphertext = new byte[pkcs8.Length];
        var tag = new byte[16];
 
        using var aes = new OpenSslAesGcm(kek);
        aes.Encrypt(nonce, pkcs8, ciphertext, tag);
 
        // 4. Create backup file
        var backup = new KeyBackup
        {
            Version = 1,
            Algorithm = "ML-DSA-65",
            CreatedAt = DateTime.UtcNow,
            KdfAlgorithm = "Argon2id",
            KdfSalt = Convert.ToBase64String(salt),
            KdfIterations = 4,
            KdfMemoryKiB = 65536,
            EncryptionAlgorithm = "AES-256-GCM",
            Nonce = Convert.ToBase64String(nonce),
            Tag = Convert.ToBase64String(tag),
            EncryptedKey = Convert.ToBase64String(ciphertext),
            Checksum = ComputeChecksum(pkcs8)
        };
 
        // 5. Save as JSON
        var json = JsonSerializer.Serialize(backup, new JsonSerializerOptions
        {
            WriteIndented = true
        });
        File.WriteAllText(backupPath, json);
 
        // 6. Clear memory
        CryptographicOperations.ZeroMemory(pkcs8);
        CryptographicOperations.ZeroMemory(kek);
 
        Console.WriteLine($"Backup created: {backupPath}");
        Console.WriteLine($"  Checksum: {backup.Checksum}");
    }
 
    public AsymmetricAlgorithm RestoreFromBackup(
        string backupPath,
        string backupPassword)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // 1. Load backup
        var json = File.ReadAllText(backupPath);
        var backup = JsonSerializer.Deserialize<KeyBackup>(json);
 
        // 2. Derive KEK (same parameters as backup)
        var salt = Convert.FromBase64String(backup.KdfSalt);
        var kek = ctx.DeriveKey(
            backupPassword,
            salt,
            outputLength: 32,
            algorithm: KeyDerivationAlgorithm.Argon2id,
            iterations: backup.KdfIterations,
            memoryKiB: backup.KdfMemoryKiB,
            parallelism: 4
        );
 
        // 3. Decrypt
        var nonce = Convert.FromBase64String(backup.Nonce);
        var tag = Convert.FromBase64String(backup.Tag);
        var ciphertext = Convert.FromBase64String(backup.EncryptedKey);
        var pkcs8 = new byte[ciphertext.Length];
 
        using var aes = new OpenSslAesGcm(kek);
        aes.Decrypt(nonce, ciphertext, tag, pkcs8);
 
        // 4. Verify checksum
        var checksum = ComputeChecksum(pkcs8);
        if (checksum != backup.Checksum)
        {
            throw new CryptographicException("Backup checksum invalid");
        }
 
        // 5. Import key
        var key = ctx.ImportPrivateKey(pkcs8, backup.Algorithm);
 
        CryptographicOperations.ZeroMemory(pkcs8);
        CryptographicOperations.ZeroMemory(kek);
 
        Console.WriteLine($"Backup restored: {backup.Algorithm}");
        return key;
    }
 
    private string ComputeChecksum(byte[] data)
    {
        var hash = SHA256.HashData(data);
        return Convert.ToHexString(hash).Substring(0, 16);
    }
}

Code Example: Shamir Secret Sharing

using SecretSharingDotNet.Cryptography;
 
public class ShamirKeyBackup
{
    public ShamirShares SplitKey(
        byte[] privateKey,
        int totalShares,
        int threshold)
    {
        // Shamir's Secret Sharing: n-of-m scheme
        // e.g., 3-of-5: At least 3 of 5 shares needed
 
        var gf = new ExtendedEuclideanAlgorithm<BigInteger>();
        var shamir = new ShamirsSecretSharing<BigInteger>(gf);
 
        // Key as BigInteger
        var secret = new BigInteger(privateKey, isUnsigned: true);
 
        // Split into shares
        var shares = shamir.MakeShares(
            (uint)threshold,
            (uint)totalShares,
            secret
        );
 
        var result = new ShamirShares
        {
            Threshold = threshold,
            TotalShares = totalShares,
            Shares = shares.Select((s, i) => new Share
            {
                Index = i + 1,
                Value = Convert.ToBase64String(s.Y.ToByteArray())
            }).ToList()
        };
 
        Console.WriteLine($"Key split into {totalShares} shares (Threshold: {threshold})");
        return result;
    }
 
    public byte[] RecombineKey(ShamirShares shares, List<int> shareIndices)
    {
        if (shareIndices.Count < shares.Threshold)
        {
            throw new ArgumentException(
                $"At least {shares.Threshold} shares needed, but only {shareIndices.Count} provided"
            );
        }
 
        var gf = new ExtendedEuclideanAlgorithm<BigInteger>();
        var shamir = new ShamirsSecretSharing<BigInteger>(gf);
 
        // Collect shares
        var selectedShares = shareIndices
            .Select(i => shares.Shares.First(s => s.Index == i))
            .Select(s => new FinitePoint<BigInteger>(
                s.Index,
                new BigInteger(Convert.FromBase64String(s.Value), isUnsigned: true)
            ))
            .ToArray();
 
        // Reconstruct secret
        var secret = shamir.Reconstruction(selectedShares);
 
        return secret.ToByteArray();
    }
 
    public void DistributeShares(ShamirShares shares, string[] recipients)
    {
        // Distribute shares to different persons/locations
        for (int i = 0; i < shares.Shares.Count && i < recipients.Length; i++)
        {
            var share = shares.Shares[i];
            var recipient = recipients[i];
 
            // In practice: Send encrypted to recipient
            Console.WriteLine($"Share {share.Index} → {recipient}");
 
            // Example: As QR code or USB stick
            var shareFile = $"share-{share.Index}-{recipient.Replace(" ", "_")}.json";
            File.WriteAllText(shareFile, JsonSerializer.Serialize(share));
        }
    }
}

Backup Strategy by Key Type

Key Type Backup Method Copies Locations Retention
Root CA Shamir 3-of-5 + HSM 5 3 geo-distributed Permanent
Intermediate CA Encrypted + HSM 3 2 locations 10 years
TLS Server Encrypted 2 Datacenter + Offsite 2 years
Code Signing Shamir 2-of-3 3 2 locations 5 years
User Keys Encrypted 2 Local + Cloud 1 year

Industry-Specific Backup Requirements

Industry Requirement Method Specifics
Financial Sector PCI-DSS HSM + Dual Control Audit log mandatory
Healthcare HIPAA Key Escrow Access for emergencies
Government VS-NfD Safe + 2-Person Security Officer
Energy KRITIS Offline Backup Air-gapped system

Relationship Scenario Description
Prerequisite 11.2 Key Storage Store keys securely
Related 11.3 Key Rotation Backup before rotation
Next Step 11.5 Key Destruction Delete old backups
Related 4.4 Certificate Backup Backup certificates

« ← 11.3 Key Rotation | ↑ Key Overview | 11.5 Key Destruction → »


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

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