Key hierarchy and the HSM
See how envelope encryption keeps a stored secret useless without KMS access.
1Claw encrypts every secret with envelope encryption. A random 256-bit DEK encrypts the value with AES-256-GCM, then a per-vault KEK that never leaves the HSM wraps the DEK. In production the HSM is Google Cloud KMS at FIPS 140-2 Level 3 protection.
- JWT signing key: one Ed25519 key per deployment, in the same KMS key ring
- KEK: one symmetric key per vault, wraps and unwraps DEKs
- DEK: fresh 256-bit key per secret version, never persisted in the clear
- KEKs rotate on a 365-day period; KMS keeps old versions for decrypt
Every KMS encrypt, decrypt, and sign includes a CRC32C checksum. If the checksum mismatches in transit, the operation fails immediately instead of returning corrupt data.
- 1
Exchange your API key for a bearer token. Replace 1ck_your_key_here with your real key from Settings → API Keys.
bashexport ONECLAW_API_KEY="1ck_your_key_here" export TOKEN=$(curl -s -X POST https://api.1claw.co/v1/auth/api-key-token \ -H "Content-Type: application/json" \ -d "{\"api_key\":\"$ONECLAW_API_KEY\"}" | jq -r .access_token) - 2
Use your vault UUID from
1claw vault listor Foundations.bashexport VAULT_ID="your-vault-uuid" - 3
Store a secret. Use a 1ck_ user key (which has full access), or an agent JWT with a write policy on this path. On the wire this is plaintext; at rest 1Claw generates a DEK, encrypts the value, and wraps the DEK with the vault KEK.
bashcurl -s -X PUT https://api.1claw.co/v1/vaults/$VAULT_ID/secrets/api-keys/demo \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"type":"api_key","value":"sk_live_demo_123"}' - 4
Read the secret back. The API returns the decrypted value; reason about what is stored at rest vs. returned in memory. The database holds only ciphertext, the wrapped DEK, IV, and tag. Without a KMS unwrap none of it decrypts.
bashcurl -s https://api.1claw.co/v1/vaults/$VAULT_ID/secrets/api-keys/demo \ -H "Authorization: Bearer $TOKEN"
You stored a secret and can now explain why a stolen database is worthless: the plaintext DEK exists only in memory during the operation, and the KEK never leaves the HSM.
Where this goes wrong in practice. The hierarchy is simple enough to draw on a whiteboard, and almost every failure comes from a gap between the drawing and the deployment.
- The application caches decrypted material. An HSM call has latency, so someone adds a cache, and the plaintext DEK now lives in process memory for the lifetime of the pod. The key never left the HSM and the secret is readable from a core dump.
- The audit log is treated as a byproduct. Non-exportability means misuse is your detection surface, so an HSM log nobody ships anywhere converts your best forensic record into a file that ages out.
- Key versions are pruned to tidy up. Rotation creates a version and old data still points at the old one. Deleting retired versions is cryptographic erasure performed by accident.
- The credential that calls the HSM is treated as ordinary. It is the whole boundary. A key file on disk is protected by the HSM; the token that authorises calls to it usually is not.
The pattern across all four: the hardware boundary is strong and everything adjacent to it is ordinary software. Attackers do not attack the boundary, they attack what stands next to it.
Decide
An engineer reports that an attacker briefly had shell on an application server. That server does not hold key material; it authenticates to the HSM and calls it to sign and unwrap. Access was revoked after roughly forty minutes.
What is the correct assessment of the damage?
Check your understanding
3 questionsWhat wraps the DEK before it is stored?
What FIPS level is the production HSM?
How often do KEKs rotate automatically?