As cryptographic best practices evolve, you will eventually need to upgrade stored password hashes to a stronger algorithm or higher cost parameters. Running a bulk migration script is impractical — it requires the plaintext password, which is never stored. Hash Forge’s approach is on-login migration: every time a user authenticates, the stored hash is verified and, if it does not meet current standards, silently re-hashed with the preferred algorithm before the response is returned. Users experience no disruption, and old hashes are phased out naturally over time.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.
Migration Methods
rotate(string, old_hash) -> str | None
rotate() verifies the plaintext string against old_hash. If verification succeeds it immediately produces a new hash with the preferred hasher and returns it. If verification fails it returns None — no exception is raised, making it safe to use directly as the return value of a login check.
rotate() returns None when verification fails. Check the return value rather than treating a non-None result as proof of identity — the method’s responsibility is migration, not authentication state.verify_and_update(string, hashed_string) -> tuple[bool, str | None]
verify_and_update() returns a two-element tuple:
bool—Trueif the password matched the stored hash,Falseotherwisestr | None— a new hash ifneeds_rehash()returnsTrue, otherwiseNone
None. Use this method when you need the authentication result and the migration signal as separate values.
Step-by-Step Migration Guide
Create a
HashManager with the target algorithm first (it becomes the preferred hasher) and all legacy algorithms you need to support for verification.from hash_forge import HashManager
manager = HashManager.from_algorithms("argon2", "pbkdf2_sha256", "bcrypt")
# preferred: argon2
# can verify: pbkdf2_sha256, bcrypt
is_valid, new_hash = manager.verify_and_update(password, stored_hash)
if not is_valid:
return login_failed()
If
new_hash is not None, the stored hash was either produced by a legacy algorithm or with outdated parameters. Save the new hash to the database before returning.Complete Login Function Example
Policy-Based Migration
PasswordHashPolicy.recommended() bundles the same multi-algorithm setup used above into a single reusable profile. Use it with HashManager.from_policy() for a more declarative approach.
Auditing Hashes Before Migration
Before rolling out a migration, useinspect() to understand the distribution of algorithms and parameters currently stored in your database.
inspect() returns None for any hash that no registered hasher recognises, which helps identify corrupt or completely unknown records before you start the migration.
Explicit Rehash Check
When you want to check whether a hash needs upgrading without verifying the password (for example, in a background audit job), useneeds_rehash() directly:
needs_rehash() returns True when:
- The algorithm used to produce the hash is not the preferred algorithm, or
- The hash was produced with parameters that no longer match the current hasher configuration (e.g. a lower iteration count)
