AES-256 is unbreakable. RSA-4096 is computationally infeasible to factor. SHA-384 has no known collisions. The algorithms are fine. The keys are the problem.
Every major encryption breach in the last decade wasn’t caused by broken algorithms — it was caused by broken key management: keys stored in plaintext config files, keys shared across environments, keys never rotated, keys that couldn’t be revoked, keys that nobody knew existed.
This guide covers the practical patterns for managing cryptographic keys in enterprise environments — not the theory (NIST SP 800-57 covers that), but the operational reality of keeping keys secure across cloud, on-premises, and hybrid infrastructure.
The Five Rules of Key Management
Before diving into specifics, these principles apply universally:
1. Keys must never exist in plaintext outside a secure boundary. A key in a config file, environment variable, source code, or email is a compromised key. Period.
2. Every key must have an owner. “The infrastructure team” is not an owner. A specific person or service account that’s responsible for the key’s lifecycle.
3. Every key must have a defined lifetime. Keys without expiry dates accumulate forever. Define the crypto-period at generation time.
4. Key access must be audited. Every time a key is used, accessed, or modified — log it. You need this for incident response and compliance.
5. Key destruction must be as deliberate as key generation. Deleting a file isn’t destruction. Zeroization in HSMs, cryptographic erasure, and documented destruction procedures are.
Key Generation: Getting It Right from the Start
Where to Generate
| Key Type | Generate In | Why |
|---|---|---|
| CA signing keys | HSM (FIPS 140-2 Level 3) | Compliance requirement, non-extractable |
| TLS server keys | On the target server | Key never travels over network |
| Data encryption keys (DEK) | KMS API call | KMS generates with hardware RNG |
| SSH keys | On the user’s machine | Private key never leaves the device |
| Code signing keys | HSM or cloud KMS | CA/B Forum requires hardware storage |
What NOT to Do
# WRONG: Generate key on a shared build server
ssh-keygen -t rsa -b 4096 -f /tmp/production.key # Key in /tmp on shared machine!
# WRONG: Generate key and email it
openssl genrsa -out key.pem 4096 && mail -a key.pem admin@company.com
# WRONG: Generate key in source code
const key = crypto.randomBytes(32); // Key exists in application memory, logs, core dumps
# RIGHT: Generate in HSM (key never leaves hardware)
pkcs11-tool --module /usr/lib/libCryptoki2_64.so --keypairgen --key-type EC:prime256v1
# RIGHT: Generate via KMS (key never exposed)
aws kms generate-data-key --key-id alias/master --key-spec AES_256
Entropy Matters
Keys are only as random as their source:
- HSM hardware RNG (TRNG): Best. Dedicated hardware entropy source.
- OS CSPRNG (
/dev/urandom,CryptGenRandom): Good. Suitable for all non-HSM key generation. - Application PRNG (
Math.random(),random.random()): NEVER. Predictable. Not cryptographically secure.
Check entropy on Linux before generating keys:
cat /proc/sys/kernel/random/entropy_avail
# Should be > 256. If low (common in VMs), install haveged or use virtio-rng.
Key Storage: The Hierarchy of Protection
Tier 1: HSM (Highest Security)
Keys generated and stored inside tamper-resistant hardware. Never extractable.
Use for: Root CA keys, payment processing keys, master encryption keys, code signing keys.
# Key exists only inside HSM — applications send data IN, get results BACK
pkcs11-tool --sign --mechanism ECDSA --input-file data.bin --id 01
# The key (id 01) never leaves the HSM. Only the signature comes out.
Tier 2: Cloud KMS (Managed Security)
Keys stored in provider-managed HSMs. Non-extractable. API-only access.
Use for: Data encryption keys, application signing, secrets wrapping.
# Key never exposed — KMS performs operations on your behalf
aws kms encrypt --key-id alias/data-key --plaintext fileb://secret.json
# Returns ciphertext. The key itself never appears in any API response.
Tier 3: Secrets Manager (Delivered to Applications)
Keys stored encrypted, delivered to applications at runtime.
Use for: Database credentials, API keys, TLS private keys (when HSM isn’t feasible).
# Application retrieves key at startup — key exists in application memory
vault kv get -field=key secret/production/encryption-key
# Risk: key is now in application memory. Minimize exposure time.
Tier 4: Encrypted File (Minimum Acceptable)
Key stored in a file, encrypted at rest, with strict file permissions.
Use for: Development environments, non-critical keys, temporary keys.
# Minimum protection for file-based keys
chmod 600 /etc/ssl/private/server.key
chown root:root /etc/ssl/private/server.key
# Still vulnerable to: root compromise, backup exposure, disk forensics
Tier 5: Plaintext (NEVER Acceptable in Production)
Key in a config file, environment variable, source code, or documentation.
# NEVER DO THIS
export DB_ENCRYPTION_KEY="a1b2c3d4e5f6..." # In .bashrc, shell history, process list
echo "key=abc123" >> application.properties # In source control, backups, logs
Key Rotation: The Patterns That Work
Pattern 1: Versioned Keys (Encryption)
Best for data encryption keys where old data must remain decryptable:
Year 1: Key v1 encrypts all data
Year 2: Key v2 encrypts NEW data. Key v1 retained for decrypting old data.
Year 3: Key v3 encrypts NEW data. v1 and v2 retained.
Background job re-encrypts old data with v3.
Once complete: destroy v1 and v2.
AWS KMS does this automatically with enable-key-rotation:
aws kms enable-key-rotation --key-id alias/data-key
# New backing key generated annually
# Old versions retained automatically for decryption
# Zero application changes required
Pattern 2: Replace and Re-issue (Signing)
For signing keys where old signatures must remain verifiable:
1. Generate new signing key
2. Publish new public key to all verifiers
3. Wait for propagation (all verifiers have new public key)
4. Switch signing to new key
5. Old public key retained for verifying old signatures
6. Old private key destroyed (can't sign new things)
Pattern 3: Short-Lived Keys (Best for TLS)
Eliminate rotation entirely by making keys ephemeral:
# cert-manager: new key pair at every renewal (every 60 days)
spec:
privateKey:
rotationPolicy: Always
# Vault PKI: 24-hour certificates, new key each time
vault write pki/issue/web-server common_name="api.example.com" ttl="24h"
No rotation procedure needed. Keys are born, used briefly, and die.
Key Destruction: The Forgotten Step
Keys that are “no longer needed” but not destroyed are attack surface. Destruction must be:
Verifiable: You can prove the key no longer exists. Irreversible: The key cannot be recovered from any source. Complete: All copies destroyed (primary, backups, archives, caches).
Destruction Methods by Storage Type
| Storage | Destruction Method |
|---|---|
| HSM | pkcs11-tool --delete-object --id 01 (hardware zeroization) |
| AWS KMS | aws kms schedule-key-deletion --pending-window-in-days 7 |
| File system | Overwrite with random data, then delete: shred -vfz -n 5 key.pem |
| Database | DELETE + VACUUM (ensure no WAL/binlog retention) |
| Backup tapes | Physical destruction or crypto-erasure of the tape |
The Destruction Checklist
Before destroying a key, verify:
- No data remains encrypted with this key (or has been re-encrypted)
- No signatures need to be verified with this key (or public key is retained separately)
- All copies identified (primary, DR, backups, dev copies, documentation)
- Destruction authorized (by key owner + security team)
- Destruction documented (date, method, who performed it, who witnessed)
Multi-Cloud Key Management
The hardest key management problem: keys across AWS, Azure, GCP, and on-premises.
The Challenge
- AWS KMS keys can’t be used in Azure
- Azure Key Vault keys can’t be used in AWS
- Neither can be exported to on-premises HSMs
- Each cloud has different APIs, different IAM models, different audit logs
The Patterns
Pattern A: Cloud-Native (Simplest)
AWS workloads → AWS KMS
Azure workloads → Azure Key Vault
GCP workloads → Google Cloud KMS
On-premises → On-premises HSM
Each environment manages its own keys. No cross-cloud key sharing. Simple but siloed.
Pattern B: BYOK (Bring Your Own Key)
Generate master key in on-premises HSM
Import (wrap) into each cloud KMS
Same key material in all environments
Gives you control over key generation. But once imported, keys are still non-exportable from each cloud. And you must manage the import process for each provider.
Pattern C: External KMS (Unified Control Plane)
Fortanix SDKMS / Thales CipherTrust / HashiCorp Vault
↓ manages keys across
AWS + Azure + GCP + On-premises
Single control plane, single audit log, single policy engine. Most complex to deploy but provides true multi-cloud key management.
Compliance Mapping
| Requirement | Standard | What It Means |
|---|---|---|
| Key generation in HSM | WebTrust, PCI PIN | CA and payment keys must be in FIPS 140-2 L3+ HSMs |
| Documented key lifecycle | PCI DSS 3.5-3.6 | Written procedures for generation, storage, rotation, destruction |
| Annual key rotation | PCI DSS, NIST 800-57 | Encryption keys rotated per defined crypto-period |
| Split knowledge | PCI PIN, WebTrust | No single person can reconstruct a critical key |
| Key destruction evidence | SOC 2, ISO 27001 | Documented proof that decommissioned keys are destroyed |
| Separation of duties | All frameworks | Key administrators ≠ key users ≠ auditors |
FAQ
Q: Should I use one key for everything or separate keys per purpose? A: Separate keys. One key per purpose (TLS, data encryption, signing) and per environment (prod, staging, dev). If one key is compromised, the blast radius is limited to that specific purpose and environment.
Q: How often should I rotate encryption keys? A: NIST SP 800-57 recommends 1-2 years for symmetric encryption keys. For TLS keys: at every certificate renewal (90 days or less). For CA signing keys: 3-5 years for intermediates, 10-20 years for roots.
Q: What’s the difference between key rotation and key re-keying? A: Rotation = new key for new operations, old key retained for old data. Re-keying = new key AND re-encrypt all existing data with the new key, then destroy the old key. Re-keying is more secure (old key fully eliminated) but operationally expensive.
Q: Can I store encryption keys in a database? A: Only if the database itself is encrypted with a key stored elsewhere (HSM or KMS). Never store the “master” key in the same system it protects. This is the envelope encryption pattern: KMS protects the key that protects the data.