Skip to content

Issue 538.2: API Key Hashing and Validation #540

@ngjunsiang

Description

@ngjunsiang

Summary

Implement secure API key generation, hashing, and validation utilities for the Campus Audit Service.

Requirements

1. Key Generation (extend campus/common/utils/secret.py)

  • Add generate_audit_api_key() -> str - Generate audit service API key
  • Format: audit_v1_<22-char-base64url> (31 total characters)
  • Example: audit_v1_kXj9mP2nQ5vR8sT7uV3wY4zX5cV6bN7m
  • Use secrets.token_urlsafe(16) for ~132-bit entropy
  • Database ID format: uid-apikey-<16-hex-chars>

2. Hashing Functions

  • hash_api_key(api_key: str) -> str - SHA-256 hash of raw key
  • verify_api_key_hash(raw_key: str, stored_hash: str) -> bool - Constant-time comparison
  • Use hmac.compare_digest() for timing-safe comparison

3. Validation Logic

  • Validate key format (prefix, length, character set)
  • Check against revoked/expired status
  • Scope validation with wildcard support
  • Rate limit bucket extraction from key metadata

4. Security Requirements

  • Never log raw API keys
  • Use constant-time comparison to prevent timing attacks
  • Hash must use SHA-256 with optional per-key salt
  • Key hash must be stored as hex string (64 chars)
  • 132-bit entropy provides strong security margin

5. Key Format Specification

Public ID (database):

uid-apikey-ab12cd34ef567890  # 16 hex chars

Secret value (authentication):

audit_v1_kXj9mP2nQ5vR8sT7uV3wY4zX5cV6bN7m  # 31 total chars
  • Prefix: audit_v1_ (9 chars) - version identification
  • Random: 22 base64url chars - URL-safe, case-sensitive
  • Entropy: ~132 bits - strong security margin
  • Comparison: Stripe uses ~130+ bits, GitHub uses 160 bits

6. Testing

  • Unit tests for key generation uniqueness
  • Tests for hash verification edge cases
  • Security tests for timing attack resistance
  • Tests for expired/revoked key detection
  • Format validation tests (prefix, length, character set)

Acceptance Criteria

  • Key generation function creates 31-char keys with audit_v1_ prefix
  • Keys use base64url encoding for URL-safe characters
  • ~132-bit entropy achieved with 22 random characters
  • Hashing functions use SHA-256 with proper salt
  • Verification uses constant-time comparison
  • Validation logic handles all edge cases
  • Security requirements enforced (no key logging, timing attacks)
  • Comprehensive unit tests with security focus
  • Performance tests for hash verification
  • Database ID format uses uid-apikey- prefix with 16 hex chars

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    Projects

    Status

    Deployed

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions