Skip to content

security: hash API keys with HMAC-SHA256, never store plaintext#12

Merged
Shaivpidadi merged 1 commit into
devfrom
feat/cipher-security-precheck-key-hashing
Apr 19, 2026
Merged

security: hash API keys with HMAC-SHA256, never store plaintext#12
Shaivpidadi merged 1 commit into
devfrom
feat/cipher-security-precheck-key-hashing

Conversation

@Shaivpidadi

Copy link
Copy Markdown
Member

Summary

API keys were stored in plaintext in the database and compared directly. A DB breach would expose all active keys.

Changes:

  • APIKey model: key column replaced with key_hash (HMAC-SHA256) + key_prefix (first 8 chars for display)
  • auth.py: incoming key is hashed before lookup — no plaintext ever touches the DB
  • key_utils.py: generate_api_key(), hash_api_key(), constant_time_compare() helpers

Required new env var

KEY_HMAC_SECRET=<random 32+ char secret>

Migration note

Existing keys in local SQLite will stop working (schema change). Re-create any test API keys after applying. For staging/production, a migration script is needed to hash existing plaintext keys — coordinate with Lambda before deploying.

Test plan

  • New API key returned on creation (plaintext, one-time only)
  • Same key accepted on subsequent requests
  • Wrong key returns 401
  • DB row contains only hash + prefix, never plaintext

🤖 Generated with Claude Code

…ompare plaintext

- APIKey model: replace plaintext `key` column with `key_hash` + `key_prefix`
- auth.py: hash incoming key before DB lookup, eliminating plaintext comparison
- key_utils.py: generate_api_key(), hash_api_key(), constant_time_compare()
- KEY_HMAC_SECRET env var required at runtime

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Shaivpidadi
Shaivpidadi merged commit 2c5dfb6 into dev Apr 19, 2026
1 check passed
@Shaivpidadi
Shaivpidadi deleted the feat/cipher-security-precheck-key-hashing branch April 19, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant