# Why You Must Encrypt API Keys at Rest
A SQL injection vulnerability in a business platform exposed their database. Among the data leaked: 3,400 plain-text API keys for services like Stripe, SendGrid, AWS, and Google APIs. Each key was a door into another system, another service, another set of customer data.
The breach wasn't the SQL injection. That was the entry point. The breach was the API keys stored as regular text fields in the database. If those keys had been encrypted, the attacker would have gotten gibberish.
## Why API Keys Are High-Value Targets
API keys are more valuable than passwords. A password gives you access to one account. An API key might give you access to:
- Payment processing (charge credit cards, issue refunds)
- Email services (send emails as the company)
- Cloud infrastructure (provision servers, access storage)
- Third-party data (customer databases, analytics platforms)
- Communication channels (SMS, push notifications)
A single compromised API key can cascade into multiple breaches across multiple services.
## The Current State
Despite this risk, a disturbing number of business platforms store API keys in plain text. A security researcher who audited 200 SaaS platforms in 2024 found that 34% stored at least some API credentials as plain text in their databases. Another 22% used reversible encoding (like Base64) that provides zero security benefit.
The reasons are predictable: "we'll add encryption later," "the database is already behind a firewall," and "nobody will have database access anyway."
These are the same reasons cited in every post-breach analysis, right before the section about how much the breach cost.
## How to Encrypt API Keys Properly
### Step 1: Choose the Right Algorithm
Use AES-256-GCM for symmetric encryption. It provides both confidentiality (the data is unreadable without the key) and authenticity (any tampering with the encrypted data is detected).
Never use: Base64 encoding (not encryption), MD5 or SHA hashing (irreversible — you can't retrieve the key), or homegrown encryption algorithms.
### Step 2: Use Envelope Encryption
Don't encrypt all API keys with the same key. Use a key hierarchy:
- A master key stored in a secure location (environment variable, HSM, key management service)
- A per-tenant or per-integration data encryption key (DEK) encrypted by the master key
- API keys encrypted by their respective DEK
If one DEK is compromised, only the keys encrypted with that specific DEK are at risk. The rest remain secure.
### Step 3: Separate Key Storage from Data Storage
The encryption key should never be stored in the same database as the encrypted data. If an attacker gains database access, they should not find the key to decrypt what they've stolen.
Common approaches:
- **Environment variables:** Simple, works for single-server deployments
- **Secrets manager:** AWS Secrets Manager, HashiCorp Vault, Azure Key Vault
- **HSM:** Hardware Security Modules for maximum security
### Step 4: Implement Key Rotation
Encryption keys should be rotated regularly. When you rotate:
1. Generate a new DEK
2. Re-encrypt all API keys with the new DEK
3. Encrypt the new DEK with the master key
4. Securely delete the old DEK
Rotation limits the damage from a compromised key: even if an attacker obtained a DEK three months ago, the current keys are encrypted with a different DEK.
### Step 5: Decrypt Only When Needed
Don't decrypt API keys and hold them in memory longer than necessary. Decrypt at the point of use, make the API call, then let garbage collection clean up the decrypted value.
Never log decrypted API keys. Never include them in error messages. Never store them in temporary files.
## The Masking Pattern
For displaying API keys in the UI, never show the full key. Show a masked version: "sk_live_...a4f2" — enough for users to identify which key it is, not enough for an attacker to use it.
When users need the full key (during initial creation), show it once and clearly communicate that it won't be shown again. This pattern is standard across Stripe, AWS, and other security-conscious platforms.
## Common Mistakes That Make Encryption Useless
### Key in the Same Database
Encrypting API keys with a key stored in a column in the same table (or even the same database) provides zero additional security. An attacker who can read the encrypted values can also read the key.
### Predictable Key Derivation
Deriving the encryption key from a predictable value (the tenant ID, a timestamp, the API key's own ID) means an attacker who understands your key derivation scheme can decrypt everything.
### Hardcoded Keys in Source Code
The encryption key committed to your Git repository is available to every developer, every CI system, and every backup of the repository. If your repo is private, it's one misconfiguration away from being public.
### No Key Rotation
Using the same encryption key for years means a key leaked at any point in the past decrypts all current data. Regular rotation limits exposure.
### Logging Decrypted Values
Application logs that include decrypted API keys create another attack vector. Log aggregation services, monitoring tools, and crash reporters all become potential leak points.
## Testing Your Key Encryption
### The Database Dump Test
Export your database and search for known API key patterns (sk_live_, AKIA, etc.). If you find matches, those keys aren't encrypted. This test should run in your CI pipeline.
### The Access Revocation Test
Revoke a developer's database access. Can they still retrieve API keys? If yes, your access controls need tightening.
### The Rotation Test
Rotate an encryption key. Verify that API integrations continue working (keys are re-encrypted with the new key). Verify that the old key no longer decrypts anything.
### The Breach Simulation Test
Simulate a database breach by examining raw database records. Can you read any API key values? You should see only encrypted ciphertext.
## The Business Case
The average cost of remediating compromised API keys: €15,000-50,000 per incident (revoking keys, rotating credentials across systems, auditing for unauthorized use, notifying affected parties).
The cost of implementing proper API key encryption: 2-3 days of engineering time, once. Plus occasional key rotation maintenance.
The math is straightforward. Encrypt your API keys. Do it now, not after the breach.