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.

ScryptHasher is a memory-hard password hasher built on Python’s stdlib hashlib.scrypt. It requires no additional dependencies. The hasher exposes all three scrypt cost axes — CPU/memory work factor (N), block size (r), and parallelism (p) — and embeds all three in the produced hash string so that verification always uses the parameters under which the hash was originally generated. It also enforces upper bounds on those stored parameters during verification to guard against denial-of-service attacks via maliciously crafted hash strings.
The work_factor parameter (N in the scrypt specification) must be a positive power of two. Providing a value that is not a power of two raises InvalidHasherError immediately in the constructor.

Import

from hash_forge.hashers import ScryptHasher
No extra dependencies are required — hashlib.scrypt is part of the Python standard library.

ScryptHasher

algorithm = 'scrypt'

Constructor

ScryptHasher(
    work_factor: int = 32768,
    block_size: int = 8,
    parallelism: int = 1,
    maxmem: int = 0,
    dklen: int = 64,
    salt_length: int = 16,
    max_work_factor: int = 2**20,
    max_block_size: int = 16,
    max_parallelism: int = 8,
)
work_factor
int
default:"32768"
CPU and memory cost parameter (N). Must be a power of two and at least 16384. Higher values increase both time and memory requirements. Raises InvalidHasherError if the value is not a power of two or is below the minimum.
block_size
int
default:"8"
Block size parameter (r). Controls the memory bandwidth used per iteration. Must be at least 8; raises InvalidHasherError otherwise.
parallelism
int
default:"1"
Parallelism parameter (p). Number of independent scrypt instances to run in parallel. Must be at least 1; raises InvalidHasherError otherwise.
maxmem
int
default:"0"
Maximum memory in bytes passed to hashlib.scrypt. When 0, the hasher auto-computes a safe value as 256 * work_factor * block_size * parallelism.
dklen
int
default:"64"
Derived key length in bytes. The resulting key is Base64-encoded before being embedded in the hash string. Must be positive; raises InvalidHasherError otherwise.
salt_length
int
default:"16"
Number of random bytes used to generate the salt. The salt is Base64-encoded and embedded in the hash string. Must be positive; raises InvalidHasherError otherwise.
max_work_factor
int
default:"1048576"
Upper bound on the work_factor accepted when verifying a stored hash. Stored hashes with a work_factor exceeding this value are rejected during verify and needs_rehash to prevent resource exhaustion.
max_block_size
int
default:"16"
Upper bound on block_size accepted when verifying a stored hash.
max_parallelism
int
default:"8"
Upper bound on parallelism accepted when verifying a stored hash.

Hash format

scrypt$<n>$<salt>$<r>$<p>$<base64_hash>
All six fields are separated by $. <n>, <r>, and <p> are the integer cost parameters; <salt> and <base64_hash> are Base64-encoded byte sequences.

Methods

hash(string: str) -> str

Hashes the given password string using hashlib.scrypt with a freshly generated random salt. The cost parameters embedded in the returned string match those the hasher was constructed with.

verify(string: str, hashed_string: str) -> bool

Parses hashed_string, validates that the embedded n, r, and p values are within the configured bounds, re-derives the scrypt key using the stored salt and cost parameters, and compares the result using hmac.compare_digest. Returns False if the hash string is malformed or if the stored parameters are outside the verification bounds.

needs_rehash(hashed_string: str) -> bool

Returns True when any of the embedded n, r, or p values differ from the current hasher configuration. Also returns False (rather than raising) if the stored parameters fail the bounds check, as the hash is considered invalid in that case.

Code example

from hash_forge.hashers import ScryptHasher

hasher = ScryptHasher(work_factor=32768, block_size=8, parallelism=1)
hashed = hasher.hash("my_secure_password")
assert hasher.verify("my_secure_password", hashed)
assert hasher.needs_rehash(hashed) == False

# Upgrading cost parameters
stronger = ScryptHasher(work_factor=65536, block_size=8, parallelism=1)
assert stronger.needs_rehash(hashed) == True

# Explicit dklen and salt_length
custom = ScryptHasher(work_factor=16384, block_size=8, parallelism=1, dklen=32, salt_length=32)
custom_hash = custom.hash("password")
assert custom.verify("password", custom_hash)

Build docs developers (and LLMs) love