4.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
This is a Python PBKDF2 password hashing utility with two implementations:
salt.py: Reference implementation with CLI that supports bothhashandverifysubcommands, plus a shortcut where runningpython3 salt.py <password>automatically invokes the hash commandsalt2.py: Alternative CLI that imports fromsalt.pyand requires explicit subcommands (generateandverify)
Both implementations use PBKDF2-HMAC-SHA256 with configurable iteration counts (default: 200,000, overridable via PBKDF2_ITERATIONS env var).
Common Commands
Running the CLI
# Hash a password (salt.py supports shortcut syntax)
python3 salt.py "MyPassword"
python3 salt.py hash "MyPassword"
# Verify a password
python3 salt.py verify <password> <salt_b64> <hash_b64>
# Alternative CLI (requires explicit subcommands)
python3 salt2.py generate "MyPassword"
python3 salt2.py verify <password> <salt_b64> <hash_b64>
Testing
# Run all tests
python3 -m pytest
# Run specific tests with verbose output
python3 -m pytest -k verify --maxfail=1 -vv
# Run tests for a specific module
python3 -m pytest tests/test_hashing.py
Dependencies
Dependencies are listed in requirements.txt. Install with:
pip install -r requirements.txt
Code Architecture
Module Structure
- salt.py: Core module containing
hash_password()andverify_password()functions, plus an integrated CLI viamain() - salt2.py: Wrapper CLI that imports from
salt.pyand provides an alternative command structure - tests/: Test suite mirroring the module structure
test_hashing.py: Tests for core hashing/verification functionstest_cli.py: Tests for CLI behavior (specificallysalt.py's shortcut syntax)
Key Functions
hash_password(password, *, iterations=None, salt_bytes=16) -> tuple[str, str]
- Generates a cryptographically secure random salt
- Derives a hash using PBKDF2-HMAC-SHA256
- Returns base64-encoded (salt, hash) tuple
verify_password(password, salt_b64, hash_b64, *, iterations=None) -> bool
- Validates a password against stored salt/hash
- Uses timing-safe comparison via
hmac.compare_digest() - Returns
Falsefor invalid base64 without raising exceptions
CLI Argument Handling
The salt.py module includes _normalize_args() which allows shortcut syntax: if the first argument is not a subcommand (hash/verify) and not a flag, it's automatically prefixed with hash. This is tested in tests/test_cli.py:test_main_supports_hash_shortcut().
Development Guidelines
Python Version and Style
- Target Python 3.11+
- Use type annotations on public functions
- 4-space indentation
- Follow
lowercase_with_underscoresnaming for functions and variables
Security Practices
- Always use
os.urandom()for salt generation (never predictable values) - Use
hmac.compare_digest()for hash comparison to prevent timing attacks - Validate base64 input with
validate=Trueparameter - Handle encoding errors gracefully by returning
Falserather than raising exceptions
Testing Requirements
- Place tests in
tests/test_<module>.pymatching the module name - Cover happy paths and error handling (invalid base64, wrong passwords)
- Include round-trip tests: hash → verify with correct/incorrect passwords
- Maintain >90% coverage for hashing utilities
- When adding new hash algorithms, include regression tests with known salt/hash pairs
Configuration
- Iteration count defaults to 200,000 but respects
PBKDF2_ITERATIONSenvironment variable - Salt size defaults to 16 bytes (configurable via
salt_bytesparameter)
Commit Guidelines
Use imperative subject lines with conventional commit prefixes:
feat:for new featuresfix:for bug fixestest:for test additions/changesrefactor:for code restructuring
Reference issues with Fixes #ID when applicable. PRs should only be opened after tests pass.