Files
password-security-python/CLAUDE.md

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 both hash and verify subcommands, plus a shortcut where running python3 salt.py <password> automatically invokes the hash command
  • salt2.py: Alternative CLI that imports from salt.py and requires explicit subcommands (generate and verify)

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() and verify_password() functions, plus an integrated CLI via main()
  • salt2.py: Wrapper CLI that imports from salt.py and provides an alternative command structure
  • tests/: Test suite mirroring the module structure
    • test_hashing.py: Tests for core hashing/verification functions
    • test_cli.py: Tests for CLI behavior (specifically salt.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 False for 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_underscores naming 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=True parameter
  • Handle encoding errors gracefully by returning False rather than raising exceptions

Testing Requirements

  • Place tests in tests/test_<module>.py matching 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_ITERATIONS environment variable
  • Salt size defaults to 16 bytes (configurable via salt_bytes parameter)

Commit Guidelines

Use imperative subject lines with conventional commit prefixes:

  • feat: for new features
  • fix: for bug fixes
  • test: for test additions/changes
  • refactor: for code restructuring

Reference issues with Fixes #ID when applicable. PRs should only be opened after tests pass.