Category: Key Management
Complexity: ⭐⭐⭐⭐ (High)
Prerequisites: Generated keys, backup infrastructure
Estimated Time: 25-35 Minutes
This scenario describes the secure backup of cryptographic keys. A well-designed backup concept is essential for business continuity and disaster recovery.
Backup Strategies:
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); } }
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)); } } }
| 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 | 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