Key Management
KMS & HSM
Hardware modules and cloud key services.
The safest key is one nobody can copy. A private key stored in a file can be exfiltrated by anyone who reads the disk, the backup, or the memory dump. Hardware Security Modules (HSMs) and Key Management Services (KMS) remove that risk by keeping the key inside a boundary and only ever performing operations with it, so there is nothing to steal.
The core property: use but never extract
Instead of handing your application the key, an HSM or KMS holds the key internally and exposes operations: “sign this hash”, “decrypt this blob”, “wrap this data key”. The raw private key never crosses the boundary, so a compromised application server can request operations but cannot walk away with the key itself.
| Model | Key location | If the app server is breached |
|---|---|---|
| Key file on disk | In your process/filesystem | Attacker copies the key: full compromise |
| KMS / HSM | Inside the module | Attacker can request ops while access lasts, but never gets the key |
This is a genuine reduction in blast radius. Revoke the breached identity’s access and the attacker loses all ability to use the key; with a stolen key file, revocation is impossible because the attacker holds a copy forever.
Cloud KMS mental model and IAM as the real perimeter
A cloud KMS (AWS KMS, GCP Cloud KMS, Azure Key Vault) is a managed service that creates and stores keys and performs crypto operations via API calls. You never see the key material. Because access is an API call, your real security perimeter is no longer file permissions: it is IAM policy. The question shifts from “who can read this file” to “which identities are allowed to call Encrypt, Decrypt, or Sign on this key, from where, and is it logged”.
app --(IAM-authenticated API call)--> KMS
"decrypt this wrapped DEK"
<--(plaintext DEK, if authorized)--
KMS pairs naturally with the envelope encryption from the sibling Key Rotation page: the KMS holds the key-encryption key and wraps/unwraps small data keys, while bulk data stays encrypted at rest with the data key. Two implications follow:
- IAM misconfiguration is the new key leak. An overly broad policy that lets any role call
Decryptundoes the hardware protection. Scope permissions tightly and audit them. - Logging is a feature. Every use is recorded, so you get an audit trail of who used which key when, which a bare key file can never give you.
When an HSM is warranted vs software keys
Not every key needs hardware. The decision is about value and obligation.
| Situation | Suggested approach |
|---|---|
| Ordinary app secrets, low blast radius | Secret store or software keys (see Key Generation & Storage) |
| Sensitive keys, want use-but-never-extract, no compliance mandate | Cloud KMS |
| Root/CA signing keys, payment keys, regulatory mandate (FIPS 140, PCI) | Dedicated HSM (or cloud HSM) |
An HSM is warranted when the key is a crown jewel (a certificate authority root, a code-signing master, payment card keys) or when a standard like FIPS 140-2/3 or PCI DSS requires certified hardware. For most application work a cloud KMS gives you the essential non-extractable property without the cost and operational weight of running dedicated hardware. Start with software keys managed well, graduate to KMS as value rises, and reserve HSMs for keys whose compromise would be catastrophic or is explicitly regulated.
Hands-on: sign with a key you never extract
You can rehearse the use-but-never-extract pattern locally: the tool operates on the key file without your application ever reading the raw bytes, mirroring how a KMS API works.
cd ~/crypto-lab
openssl genpkey -algorithm ed25519 -out kms-sim.pem
chmod 600 kms-sim.pem
echo -n "authorize payment #4417" > txn.txt
# The "signing service" holds the key; the caller only gets a signature back
openssl pkeyutl -sign -inkey kms-sim.pem -rawin -in txn.txt -out txn.sig
openssl pkeyutl -verify -pubin \
-inkey <(openssl pkey -in kms-sim.pem -pubout) \
-rawin -in txn.txt -sigfile txn.sig
Expected output:
Signature Verified Successfully
In a real KMS the private key would live in the service and the -sign step would be a kms sign API call, so the key never touches your host at all.
Practical Guidance
- Prefer use-but-never-extract for any valuable key: let a KMS or HSM perform operations rather than handing keys to your app.
- Treat IAM policy as your real key perimeter. Scope
Encrypt/Decrypt/Signpermissions to the minimum identities and audit them. - Combine KMS with envelope encryption: keep the KEK in the KMS, wrap data keys, and rotate the KEK without re-encrypting data.
- Turn on and review KMS access logs; the audit trail is a core reason to use one.
- Reserve dedicated HSMs for crown-jewel keys (CA roots, code-signing, payment) or when FIPS/PCI mandates certified hardware.
- Do not over-engineer: manage ordinary secrets well in a secret store first, and escalate to KMS then HSM as the key’s value grows.