API Key Hasher: Why SHA-256 Is Enough for High-Entropy Secrets
Password hashing guides insist on bcrypt or Argon2 for good reason — but that advice doesn't automatically apply to API keys. A properly generated API key already carries 128+ bits of random entropy, which changes the security calculus entirely: a fast hash like SHA-256 is appropriate here, while a slow password hash would just waste server CPU for no real security benefit.
Compare an incoming key by hashing it the same way and checking for a match — never store the plaintext key.
Why Password Hashing Rules Don't Apply Here
bcrypt and Argon2 exist specifically to slow down brute-force attacks against low-entropy, human-chosen passwords, where an attacker might guess 'password123' in one try. An API key generated with a CSPRNG has no guessable structure — brute-forcing 128 bits of true randomness is infeasible regardless of how fast or slow the hash function is, so a fast, well-understood hash like SHA-256 is the correct tool.
The Threat Model: Database Breach, Not Guessing
Hashing API keys protects against a specific scenario: your database gets breached, and the attacker gets read access to stored hashes. Without hashing, they'd have immediately-usable API keys. With hashing, they'd need to reverse a one-way function — computationally infeasible for SHA-256 — so the leaked hashes are useless to them directly.
Pepper: Protection Even If Hashes Leak Too
A pepper — a secret value stored server-side (env variable, secrets manager), never in the database — adds a layer that survives even a full database breach. Since the pepper isn't stored alongside the hash (unlike a per-record salt), an attacker with only database access can't reproduce HMAC-SHA256(key, pepper) even if they somehow guessed the original key.
Practical Examples
Storing a New API Key
What actually goes in the database.
- 1.Generate: sk_live_a1b2c3...
- 2.Show the plaintext key to the user once
- 3.Store only: SHA-256(sk_live_a1b2c3...) in the database
Verifying an Incoming Request
Comparing without ever storing plaintext.
- 1.Request arrives with: Authorization: Bearer sk_live_a1b2c3...
- 2.Server computes: SHA-256(incoming_key)
- 3.Compares to stored hash — match means valid
What This Tool Computes
- SHA-256: standard one-way digest
- HMAC-SHA256: with an optional pepper
- All via native Web Crypto: no custom crypto implementation
When You'd Want bcrypt/Argon2 Instead
- Hashing user-chosen passwords (low entropy, guessable)
- Any secret a human might have typed, not generated randomly
- See our Bcrypt Hash Generator for that case specifically
Frequently Asked Questions
Why is plain SHA-256 fine for API keys but not for passwords?
Password hashing needs to resist brute-forcing over a small, guessable space (dictionary words, common patterns) — that's what slow, salted algorithms like bcrypt and Argon2 are for. A properly generated API key already has 128+ bits of random entropy, making brute-force infeasible regardless of hash speed — the fast SHA-256 digest is sufficient because the input itself, not the hash function, is what resists guessing.
Why hash API keys at all instead of storing them directly?
If your database is ever breached, stored hashes can't be directly used as valid keys — an attacker would need to reverse the hash (infeasible for SHA-256) rather than just read the value. To authenticate a request, you hash the incoming key the same way and compare it to the stored hash.
What is a 'pepper' and how is it different from a salt?
A pepper is a secret value kept outside the database (in an environment variable or secrets manager), mixed in via HMAC. Unlike a per-record salt (which is stored alongside the hash and doesn't need to be secret), a pepper adds protection even if the entire database — hashes included — is stolen, since the attacker still doesn't have the pepper.
Do I need a unique salt per key like I would for passwords?
It's less critical for high-entropy random keys than for passwords, since precomputed rainbow-table attacks are already infeasible against 128-bit random values. A shared HMAC pepper across all keys is a reasonable, simpler approach specifically because the keys themselves are already unguessable.
Is my API key sent anywhere when I use this tool?
No — hashing happens entirely in your browser via the Web Crypto API. That said, avoid pasting real production secrets into any browser tool as a general practice; test with a placeholder value when possible.
Can I reverse a SHA-256 hash back to the original key?
Not feasibly — SHA-256 is a one-way cryptographic hash function. There's no decryption; verification works by hashing an incoming key the same way and comparing the two hashes.