password

package
v0.10.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 10 Imported by: 0

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

View Source
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

View Source
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 Hash

func Hash(plaintext string) (string, error)

Hash derives a PHC-encoded Argon2id hash at the current parameters.

func HashWith

func HashWith(plaintext string, p Params) (string, error)

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

func NeedsRehash(encoded string) (bool, error)

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).

func Verify

func Verify(plaintext, encoded string) (bool, error)

Verify reports whether plaintext produced encoded. A malformed or out-of-bounds stored hash is an error, never a silent fall back to the compiled defaults.

Types

type Params

type Params struct {
	Memory  uint32
	Time    uint32
	Threads uint8
}

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.

func (Params) Validate

func (p Params) Validate() error

Validate reports whether these parameters are inside the band a stored hash may carry.

The band is parse's, not a second opinion: minting something Verify would refuse is a hash that works nowhere, which is a worse failure than being told no.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL