Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Zozi96/hash-forge/llms.txt

Use this file to discover all available pages before exploring further.

PasswordHashPolicy is a frozen dataclass that encodes the rules governing which algorithms are acceptable for new hashes, which may still be used for verification of legacy data, and what per-algorithm construction parameters to use. When a policy is attached to a HashManager (via HashManager.from_policy), it is consulted on every hash, verify, and needs_rehash call, ensuring consistent enforcement across the application.
from hash_forge import PasswordHashPolicy

Built-in Profiles

Hash Forge ships four ready-made profiles covering the most common deployment scenarios. Each is a classmethod that returns a fully populated PasswordHashPolicy instance.
@classmethod
def recommended(cls) -> PasswordHashPolicy
The modern default profile. Argon2 is the preferred algorithm with conservative cost parameters; PBKDF2-SHA256, bcrypt-SHA256, and Scrypt are registered for verifying and migrating existing hashes.
SettingValue
Preferred algorithmargon2
time_cost3
memory_cost65 536 KiB
parallelism1
hash_len32
Migration algorithmspbkdf2_sha256, bcrypt_sha256, scrypt
policy = PasswordHashPolicy.recommended()
manager = HashManager.from_policy(policy)

fips

@classmethod
def fips(cls) -> PasswordHashPolicy
A FIPS 140-compatible profile. Uses exclusively PBKDF2-HMAC-SHA256 at 600,000 iterations (meeting NIST SP 800-132 guidance), with PBKDF2-SHA1 available for legacy verification only.
SettingValue
Preferred algorithmpbkdf2_sha256
iterations600 000
Migration algorithmspbkdf2_sha1
policy = PasswordHashPolicy.fips()
manager = HashManager.from_policy(policy)
Use this profile when deploying to environments with FIPS-mode OpenSSL or US federal compliance requirements. Argon2 and bcrypt are intentionally excluded — they are not FIPS-approved primitives.

legacy_compat

@classmethod
def legacy_compat(cls) -> PasswordHashPolicy
A wide-compatibility profile for applications migrating from older systems. New hashes use PBKDF2-SHA256; the manager can still verify hashes produced by PBKDF2-SHA1, bcrypt, bcrypt-SHA256, Scrypt, and RIPEMD-160.
SettingValue
Preferred algorithmpbkdf2_sha256
iterationsDEFAULT_PBKDF2_ITERATIONS (150 000)
allow_legacy_verifyTrue
Verification algorithmspbkdf2_sha1, bcrypt, bcrypt_sha256, scrypt, ripemd160
policy = PasswordHashPolicy.legacy_compat()
manager = HashManager.from_policy(policy)

calibrate

@classmethod
def calibrate(cls, target_ms: int = 250) -> PasswordHashPolicy
Auto-tunes the PBKDF2-SHA256 iteration count so that a single hash operation takes approximately target_ms milliseconds on the current machine. The method doubles the iteration count until the target is reached (up to a hard ceiling of 2,000,000 iterations), then returns a PBKDF2-only policy.
target_ms
int
Target hash duration in milliseconds. Defaults to 250.
Returns: PasswordHashPolicy with a calibrated pbkdf2_sha256 iteration count.
# Tune for ~350 ms on this server
policy = PasswordHashPolicy.calibrate(target_ms=350)
manager = HashManager.from_policy(policy)
Run calibration once at application startup or as a one-off script during deployment. Store the resulting iteration count in your HashForgeConfig or environment variables so it remains stable across restarts.

Constructor Fields

PasswordHashPolicy is a frozen dataclass — all fields are set at creation time and cannot be mutated.
preferred_algorithm
AlgorithmType
required
The algorithm used for all new password hashes. Must be included in algorithms.
algorithms
tuple[AlgorithmType, ...]
required
Complete ordered tuple of algorithm identifiers registered with the policy. The preferred algorithm should appear first.
algorithm_options
dict[str, dict[str, Any]]
Per-algorithm constructor keyword arguments. Keys are algorithm names; values are dicts passed to HasherFactory.create. Defaults to {}.
algorithm_options={
    "argon2": {"time_cost": 3, "memory_cost": 65536},
    "pbkdf2_sha256": {"iterations": 200_000},
}
allow_legacy_verify
bool
When True (default), legacy-category algorithms such as pbkdf2_sha1 and ripemd160 may still be used for hash verification. When False, any verify call targeting a legacy hasher returns False.
allow_digest_password_hashing
bool
When False (default), calling hash() with a digest algorithm (blake2, sha3_256, etc.) raises ValueError. Fast digests are not suitable for password hashing and this guard prevents accidental misuse.
allow_deprecated_hashing
bool
When False (default), calling hash() with a deprecated algorithm (whirlpool) raises ValueError.
max_verify_costs
dict[str, dict[str, int]]
Maximum accepted cost parameters for verification. Currently used by Scrypt to reject hashes that were produced with implausibly high cost factors. Defaults to {}.
max_verify_costs={
    "scrypt": {"work_factor": 1_048_576, "block_size": 16, "parallelism": 8},
}

Instance Methods

options_for

def options_for(self, algorithm: str) -> dict[str, Any]
Returns the constructor keyword arguments for a given algorithm as configured in algorithm_options. For Scrypt, any max_verify_costs entries are merged in automatically.
algorithm
str
required
The algorithm name to look up.
Returns: dict[str, Any] — constructor kwargs (empty dict if no options were set).
opts = policy.options_for("argon2")
# {'time_cost': 3, 'memory_cost': 65536, 'parallelism': 1, 'hash_len': 32}

validate_for_hashing

def validate_for_hashing(self, algorithm: str) -> None
Checks whether algorithm is acceptable for producing new hashes under this policy. Raises ValueError for any of the following conditions:
ConditionGuard flag
Algorithm is "deprecated" categoryallow_deprecated_hashing is False
Algorithm is "digest" categoryallow_digest_password_hashing is False
Algorithm is "legacy" category and not the preferred algorithmAlways blocked
algorithm
str
required
The algorithm name to validate.
Returns: None on success; raises ValueError on failure.

validate_for_verify

def validate_for_verify(self, algorithm: str) -> None
Checks whether algorithm is allowed for verifying an existing hash. Currently enforces the allow_legacy_verify flag for legacy-category algorithms.
algorithm
str
required
The algorithm name to validate.
Returns: None on success; raises ValueError when legacy verify is blocked.

needs_update

def needs_update(self, algorithm: str, manager_needs_rehash: bool) -> bool
Returns True when a successfully verified hash should be rotated to a newer hash. The check combines two conditions with logical OR:
  1. The hash’s canonical algorithm differs from the policy’s preferred algorithm.
  2. The hasher’s own needs_rehash check returned True (e.g. parameters changed).
algorithm
str
required
The algorithm that produced the hash being evaluated.
manager_needs_rehash
bool
required
The result of the hasher’s own parameter-level rehash check.
Returns: bool

Helper Functions

The following utilities are exported from hash_forge alongside PasswordHashPolicy:

classify_algorithm

def classify_algorithm(algorithm: str) -> AlgorithmCategory
Classifies an algorithm into one of four categories:
from hash_forge import classify_algorithm

classify_algorithm("argon2")       # "password"
classify_algorithm("ripemd160")    # "legacy"
classify_algorithm("blake2")       # "digest"
classify_algorithm("whirlpool")    # "deprecated"

canonical_algorithm

def canonical_algorithm(algorithm: str) -> str
Resolves algorithm aliases to their canonical identifier:
from hash_forge import canonical_algorithm

canonical_algorithm("blake2b")    # "blake2"
canonical_algorithm("RIPEMD-160") # "ripemd160"
canonical_algorithm("argon2")     # "argon2"  (unchanged)

AlgorithmCategory

AlgorithmCategory = Literal["password", "legacy", "digest", "deprecated"]
The string literal type returned by classify_algorithm. Import it for type annotations:
from hash_forge import AlgorithmCategory
ValueAlgorithms
"password"argon2, bcrypt, bcrypt_sha256, pbkdf2_sha256, scrypt
"legacy"pbkdf2_sha1, ripemd160, RIPEMD-160
"digest"blake2, blake2b, blake3, sha3_256, sha3_512
"deprecated"whirlpool

Build docs developers (and LLMs) love