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.
Password hashing algorithms are fundamentally different from general-purpose cryptographic digests. Where a digest like SHA-3 is designed to be as fast as possible, a password hasher is designed to be intentionally slow and memory-intensive — properties that make offline brute-force attacks expensive even when an attacker has access to the raw hash. Hash Forge ships six password-specific algorithms: Argon2, bcrypt, bcrypt-SHA256, PBKDF2-SHA256, PBKDF2-SHA1, and Scrypt. Each one stores all parameters needed for verification inside the hash string itself, so Hash Forge can route any stored hash to the correct hasher automatically.
Every password hash produced by Hash Forge is prefixed with the algorithm identifier followed by a $ delimiter. This prefix is what allows HashManager.verify() to dispatch to the right hasher without any additional bookkeeping on your part. The formats for each algorithm are documented in the sections below.
Argon2
Argon2 is the winner of the 2015 Password Hashing Competition and is the recommended default for new projects. It is a memory-hard function with three independently tunable cost axes — time, memory, and parallelism — giving you fine-grained control over how expensive each hash operation is. Hash Forge delegates to the argon2-cffi library.
Install the extra:
pip install "hash-forge[argon2]"
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
time_cost | int | None | library default (3) | 2 | Number of iterations |
memory_cost | int | None | library default (65536) | 32768 | Memory usage in KiB |
parallelism | int | None | library default (1) | 1 | Degree of parallelism |
hash_len | int | None | library default (32) | 1 | Output hash length in bytes |
salt_len | int | None | library default | 1 | Salt length in bytes |
Passing None for any parameter defers to the argon2.PasswordHasher library defaults. Security minimums are enforced when an explicit value is provided: time_cost must be ≥ 2, memory_cost must be ≥ 32,768 KiB.
Usage:
from hash_forge import HashManager
from hash_forge.hashers import Argon2Hasher
# Using default parameters (recommended)
hasher = Argon2Hasher()
# Customised parameters
hasher = Argon2Hasher(time_cost=4, memory_cost=131072, parallelism=2, hash_len=32)
hash_manager = HashManager(hasher)
hashed = hash_manager.hash("my_secure_password")
is_valid = hash_manager.verify("my_secure_password", hashed)
# Or via the policy API for the recommended preset
from hash_forge import PasswordHashPolicy
hash_manager = HashManager.from_policy(PasswordHashPolicy.recommended())
The recommended() policy preset configures Argon2 with time_cost=3, memory_cost=65536, parallelism=1, and hash_len=32.
Hash format:
argon2$<argon2-cffi output>
The argon2-cffi output embeds the Argon2 variant, version, cost parameters, Base64-encoded salt, and Base64-encoded hash, all delimited by $. The argon2 prefix is prepended by Hash Forge to enable automatic algorithm routing.
bcrypt
bcrypt is the long-established industry standard for password hashing. It uses an adaptive cost factor (rounds) to remain resistant to hardware improvements over time. Hash Forge requires the bcrypt library.
bcrypt silently truncates passwords longer than 72 bytes. If your application accepts long passwords or passphrases, use bcrypt_sha256 instead, which pre-digests the password with SHA-256 to remove the truncation limit.
Install the extra:
pip install "hash-forge[bcrypt]"
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
rounds | int | 12 | 12 | Log-2 work factor (2^rounds iterations) |
Usage:
from hash_forge import HashManager
from hash_forge.hashers import BCryptHasher
hasher = BCryptHasher(rounds=12)
hash_manager = HashManager(hasher)
hashed = hash_manager.hash("my_secure_password")
is_valid = hash_manager.verify("my_secure_password", hashed)
# Or via quick_hash
hashed = HashManager.quick_hash("my_secure_password", algorithm="bcrypt", rounds=12)
Hash format:
bcrypt$<2b>$<rounds>$<hash>
The stored format is the algorithm prefix bcrypt concatenated directly with the raw bcrypt output (which begins with $2b$). The resulting string encodes the version, rounds, salt, and digest in the standard bcrypt layout. Hash Forge uses the bcrypt$ prefix for routing purposes.
bcrypt-SHA256
bcrypt-SHA256 is identical to bcrypt except that the input password is first run through a SHA-256 digest and hex-encoded before being passed to bcrypt. This raises the effective password length limit from 72 bytes to the full output of SHA-256, making it safe for arbitrarily long passwords and passphrases. It uses the same bcrypt extra.
Install the extra:
pip install "hash-forge[bcrypt]"
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
rounds | int | 12 | 12 | Log-2 work factor (2^rounds iterations) |
Usage:
from hash_forge import HashManager
from hash_forge.hashers import BCryptSha256Hasher
hasher = BCryptSha256Hasher(rounds=12)
hash_manager = HashManager(hasher)
hashed = hash_manager.hash("a very long passphrase that exceeds 72 bytes and is now safe")
is_valid = hash_manager.verify("a very long passphrase that exceeds 72 bytes and is now safe", hashed)
# Or via quick_hash
hashed = HashManager.quick_hash("my_secure_password", algorithm="bcrypt_sha256", rounds=12)
Hash format:
bcrypt_sha256$<2b>$<rounds>$<hash>
The stored format is the algorithm prefix bcrypt_sha256 concatenated directly with the raw bcrypt output (which begins with $2b$). The trailing segments reflect the bcrypt internal representation (version, cost, combined salt and hash), making the stored format self-describing.
PBKDF2-SHA256
PBKDF2-SHA256 is a NIST-approved, FIPS-compatible key derivation function from Python’s standard library — no extra installation required. It applies HMAC-SHA256 over the password and a random salt for a configurable number of iterations. Hash Forge enforces a minimum of 150,000 iterations to meet current OWASP guidance.
No extra installation required (uses Python’s hashlib).
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
iterations | int | 150,000 | 150,000 | HMAC rounds |
salt_length | int | 16 | — | Salt length in bytes |
Usage:
from hash_forge import HashManager
from hash_forge.hashers import PBKDF2Sha256Hasher
# Default parameters — meets OWASP minimums
hasher = PBKDF2Sha256Hasher()
# Higher iterations for stronger protection
hasher = PBKDF2Sha256Hasher(iterations=200_000)
hash_manager = HashManager(hasher)
hashed = hash_manager.hash("my_secure_password")
is_valid = hash_manager.verify("my_secure_password", hashed)
# FIPS policy profile (600,000 iterations)
from hash_forge import PasswordHashPolicy
hash_manager = HashManager.from_policy(PasswordHashPolicy.fips())
Hash format:
pbkdf2_sha256$<iterations>$<salt>$<hash>
All four fields are stored in the hash string, so Hash Forge can verify hashes produced with any past iteration count while still detecting when a rehash is needed.
PBKDF2-SHA1
PBKDF2-SHA1 is the legacy predecessor to PBKDF2-SHA256. It shares the same implementation, constructor signature, and hash format, but uses SHA-1 as the underlying HMAC digest. Hash Forge classifies it as legacy and will block its use for new hashes unless it is set as the preferred_algorithm in a policy.
PBKDF2-SHA1 should only be used to verify existing hashes stored by older systems. Do not use it for new password hashing — prefer pbkdf2_sha256 or argon2 instead.
No extra installation required (uses Python’s hashlib).
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
iterations | int | 150,000 | 150,000 | HMAC rounds |
salt_length | int | 16 | — | Salt length in bytes |
Usage:
from hash_forge import HashManager
from hash_forge.hashers import PBKDF2Sha1Hasher, PBKDF2Sha256Hasher
# Verify old PBKDF2-SHA1 hashes while issuing new ones with PBKDF2-SHA256
hash_manager = HashManager(
PBKDF2Sha256Hasher(), # preferred — used for all new hashes
PBKDF2Sha1Hasher(), # fallback — used only for verification
)
is_valid = hash_manager.verify("my_secure_password", legacy_hash)
# Or via the legacy_compat policy profile
from hash_forge import PasswordHashPolicy
hash_manager = HashManager.from_policy(PasswordHashPolicy.legacy_compat())
Hash format:
pbkdf2_sha1$<iterations>$<salt>$<hash>
Scrypt
Scrypt is a memory-hard password hashing function from Python’s standard library. It requires both significant CPU time and memory, making it resistant to hardware acceleration. The work_factor (N) parameter must always be a power of two; Hash Forge validates this at construction time.
No extra installation required (uses Python’s hashlib).
Constructor parameters:
| Parameter | Type | Default | Minimum | Description |
|---|
work_factor | int | 32768 | 16384 | CPU/memory cost (N). Must be a power of 2. |
block_size | int | 8 | 8 | Block size (r) |
parallelism | int | 1 | 1 | Parallelisation factor (p) |
dklen | int | 64 | 1 | Derived key length in bytes |
salt_length | int | 16 | 1 | Salt length in bytes |
maxmem | int | 0 | — | Maximum memory in bytes (0 = auto-calculated) |
max_work_factor | int | 1048576 | — | Upper bound on work_factor accepted during verification |
max_block_size | int | 16 | — | Upper bound on block_size accepted during verification |
max_parallelism | int | 8 | — | Upper bound on parallelism accepted during verification |
work_factor must be a power of two (e.g. 16384, 32768, 65536). Hash Forge raises InvalidHasherError if a non-power-of-two value is passed.
Usage:
from hash_forge import HashManager
from hash_forge.hashers import ScryptHasher
# Default parameters
hasher = ScryptHasher()
# Higher work factor for stronger protection
hasher = ScryptHasher(work_factor=65536, block_size=8, parallelism=1)
hash_manager = HashManager(hasher)
hashed = hash_manager.hash("my_secure_password")
is_valid = hash_manager.verify("my_secure_password", hashed)
# Via quick_hash
hashed = HashManager.quick_hash(
"my_secure_password",
algorithm="scrypt",
work_factor=32768,
block_size=8,
parallelism=1,
)
Hash format:
scrypt$<n>$<salt>$<r>$<p>$<base64_hash>
The stored format includes the work_factor (n), block_size (r), and parallelism (p) so that verify() can reconstruct the exact derivation, and needs_rehash() can detect when parameters have changed. The derived key is Base64-encoded.