Keys and operations
Store and limit keys
Keep keys out of source and normal logs, use managed key services where appropriate, and grant only required encrypt, decrypt, sign, or verify operations.
A key’s storage and permissions are part of the cryptographic design. The strongest algorithm cannot protect an exposed key, and most real-world crypto failures are key-handling failures, not broken math.
Start with the obvious exclusions. Keys never go in source control, and never in normal logs. A key committed once lives in git history forever, so treat any committed key as compromised and rotate it — deleting the file changes nothing:
git log -p --all -S 'BEGIN PRIVATE KEY' -- '*'
# any hit here means the key is burned, even if the file is gone
Where keys should live
Prefer a KMS, HSM, secure enclave, or protected secret store that can restrict operations and record use. The ladder looks like this: environment variables injected at deploy are better than files in the repo; a secret manager with access control and audit is better than environment variables; a KMS that performs operations without releasing the key is better still.
That last step changes the model. A managed key service can expose only a sign operation and keep raw key material inside the service. Your code sends bytes and receives a signature. Nothing that runs in your process can copy a key that never enters your process. This narrows authority, but access policy and audit logs become part of the cryptographic system — misconfigure the policy and the HSM protects an operation anyone can invoke.
Grant operations, not keys
Permissions should name operations, not just keys. An identity that verifies webhooks needs verify, never sign. A service that encrypts uploads needs encrypt, not decrypt:
identity key allowed
api-server webhook-hmac verify
upload-worker storage-kek encrypt
restore-job storage-kek decrypt
release-pipeline signing-v3 sign
Here is why the narrow grant matters. A signing key is available as plaintext to the whole CI job, including formatting and test steps. A compromised test dependency can copy the same authority used for releases. Scope the key to the one signing step, or better, keep it in a service that only that step’s identity may call.
Separate keys by environment and purpose, and keep data and keys under different access paths when the architecture allows it. A backup containing both ciphertext and its keys protects nothing.
Practice
Build a key inventory with purpose, owner, environment, storage, allowed operations, users, rotation, and revocation. Save the effective policy and one audit event for an authorized test operation. Then attempt a forbidden operation, such as decrypting with a sign-only identity, and capture the denial.
Lesson completed