One policy, four algorithms
Argon2id, bcrypt, scrypt and PBKDF2 behind one Policy. New hashes use its algorithm; any of the four verifies.
How a policy worksOpen-source Rust library
hsh hashes passwords with Argon2id, bcrypt, scrypt or PBKDF2 under one policy, and when a stored hash falls behind that policy, the next successful sign-in replaces it.
What it does
Each card opens its section on the features page.
Argon2id, bcrypt, scrypt and PBKDF2 behind one Policy. New hashes use its algorithm; any of the four verifies.
How a policy worksWhen a stored hash is weaker than the policy, a successful verify returns a fresh hash to save in its place.
How upgrades happenAn HMAC-SHA-256 pepper with numbered keys, so a stolen database alone cannot be cracked offline.
How the pepper worksA FIPS policy hashes only with PBKDF2 through the AWS-LC FIPS module, and refuses to hash at all in a build that cannot.
What the mode guaranteesbcrypt input over 72 bytes is rejected, not truncated; comparisons are constant time; secrets are wiped from memory.
See the railshsh hashes, verifies, rehashes and inspects from the shell, and calibrates the cost to your hardware.
Use it from the shellAlgorithms
Policy::owasp_minimum_2025() starts from these parameters. Every one can be raised.
Default
19,456 KiB of memory, 2 passes, 1 lane. Memory-hard, the recommended choice for new systems.
Compare the algorithmsLegacy and compatibility
bcrypt at cost 10 with a 72-byte limit; scrypt at N = 217, r = 8, p = 1.
Compare the algorithmsFIPS 140-3
HMAC-SHA-256 with 600,000 iterations. The only one of the four with FIPS-validated implementations.
The FIPS modeInstall
Hash with a policy, then verify with the same policy: a hash that has fallen behind comes back upgraded. The library needs Rust 1.85 or newer.
use hsh::{api, Outcome, Policy};
fn main() -> Result<(), hsh::Error> {
let policy = Policy::owasp_minimum_2025();
let stored = api::hash(&policy, "correct horse")?;
match api::verify_and_upgrade(&policy, "correct horse", &stored)? {
Outcome::Valid { rehashed: Some(new) } => { /* save new */ }
Outcome::Valid { rehashed: None } => { /* signed in */ }
Outcome::Invalid => { /* deny */ }
}
Ok(())
}hsh refuses rather than degrades: no silent truncation, no silent fallback from a FIPS policy, no peppered hash accepted without its key.
hsh is at 0.0.x and has not had a third-party audit. The security page lists what is checked, what is a stub, and what is not promised.
In numbers
Counted from hsh 0.0.10, the latest release of the library on crates.io.
hsh, the Hash (HSH) project, is a free, open-source password hashing library for Rust. You describe how passwords should be stored in a Policy; api::hash turns a password into a PHC string to store, and api::verify_and_upgrade checks a password against a stored hash and, when the hash was made under an older or weaker policy, returns a new one to save. It supports Argon2id, bcrypt, scrypt and PBKDF2, an optional pepper and a FIPS 140-3 mode, and is dual-licensed under Apache-2.0 or MIT.
The old version of this site said so; it is not a claim hsh makes. hsh stores passwords with the established password-hashing functions above. For post-quantum key exchange or signatures, use a library built for them.
0.0.10, the latest release of the hsh library on crates.io, published on 27 May 2026. The repository is tagged 0.0.12, but that release did not reach crates.io for the library or the command-line tool. The changelog has the detail.
hsh is written by Sebastien Rousseau and its contributors. The source, the issue tracker and every release are on GitHub; the crates are on crates.io. Read more on the about page.