Documentation
¶
Overview ¶
Package password hashes and verifies passwords with Argon2id.
The suite ran three algorithms and five parameter sets: Argon2id at t=1 in ky_server_base and gridlock-server, at t=3 in kysignon-server, kyrecovery-server and kydns-server (p=2 there, p=4 elsewhere), and scrypt at N=2^17 in kynotes-server and kypost-server and N=2^15 in kybookmarks-server. The Argon2 encodings are mutually parseable, so a hash minted at t=1 verified in a t=3 product at a third of the intended attacker cost and nothing flagged it.
This package is the suite's one answer: RFC 9106's second recommended profile, 64 MiB at t=3 p=4, self-describing in PHC form.
It is the only package in this module with a dependency. Argon2 is not in the standard library and is not on a proposal track, so the module's rule bends exactly once, here, and TestModuleDependenciesAreAllowlisted holds the line at x/crypto.
Index ¶
Constants ¶
const ( MaxMemoryKiB = budgetKiB MaxLanes = budgetLanes )
MaxMemoryKiB and MaxLanes are the two dimensions of this package's derivation budget, taken together under one acquirer so two waiters can never each hold part of what the other needs. They are exported so a product running derive as well can add the two budgets up rather than assume one of them is the whole story. Memory is in KiB, matching Params.Memory and every other memory value in this package.
Both are derived from unexported constants, which keeps them from drifting apart, but also keeps the number out of godoc for anyone reading pkg.go.dev rather than the source. Stated here so it doesn't have to be: MaxMemoryKiB is currently 262144 KiB (256 MiB); MaxLanes is currently 16.
Variables ¶
var ( // ErrBusy reports that too many derivations are already running. Callers should // answer 503 and must not spend a lockout strike: this is the server saying "not // now", not the user getting the password wrong. ErrBusy = errors.New("password: too many concurrent derivations") // ErrMalformed reports a stored hash that is not a well-formed Argon2id PHC string. // It is never treated as a verification failure against default parameters. ErrMalformed = errors.New("password: stored hash is not a valid argon2id PHC string") )
Functions ¶
func DummyVerify ¶
func DummyVerify()
DummyVerify spends the cost of a verification and reports nothing.
A login that answers "no such account" faster than "wrong password" enumerates accounts. Call this on every reject path that did not reach a real Verify, so the two cost the same.
It is not perfect and should not be sold as such: Verify can return ErrBusy without deriving anything, and that path is fast. Under load the oracle reopens. Shedding is still the right answer to overload — just do not describe this as constant time. The first call in a process additionally mints the dummy hash, so it costs roughly two derivations rather than one; every call after that costs one.
func HashWith ¶
HashWith derives a PHC-encoded Argon2id hash at the given parameters.
Hash is the suite's answer and what production code should call. This exists for two callers: a test suite that cannot afford 64 MiB per derivation, and a product that must mint at parameters an existing deployment already uses. Parameters are bounded to the band Verify accepts, so this cannot mint a hash that verifies nowhere — but it can mint a weaker one than the suite standard, and that is the caller's responsibility.
func NeedsRehash ¶
NeedsRehash reports whether a stored hash was made below the current parameters, so a deployment can upgrade it on the next successful login.
A hash this package did not write — malformed, foreign, or otherwise unparseable — is not stale, it is not ours: this reports false rather than guessing. Verify still refuses a foreign hash outright.
The error return is currently always nil. It is kept for signature stability: several migration plans are already written against (bool, error).
Types ¶
type Params ¶
Params are the Argon2id cost parameters. Memory is in KiB.
func DefaultParams ¶
func DefaultParams() Params
DefaultParams returns RFC 9106's second recommended option. The first asks for 2 GiB, which no login endpoint can afford per request.
A function rather than a variable: an exported var is global policy any importer can assign to, and a configuration reload writing it while a login reads it is a data race that also lets two concurrent hashes use different parameters. Callers wanting other costs pass a Params to a call, they do not edit everyone else's.