Skip to content
Zever
Home

Password hashing

Hash and verify passwords with Argon2id and rehash when parameters change.

1 min readEdit on GitHub

password hashes, verifies, and flags rehashing with Argon2id; it issues no tokens and stores nothing.

Terminal window
PASSWORD_ADAPTER=argon2id
PASSWORD_TIME=3
PASSWORD_MEMORY=65536
PASSWORD_THREADS=4
Terminal window
PASSWORD_ADAPTER=argon2id

Defaults: time 3 (1 to 10), memory 65536 KiB (64 MiB; 8 MiB to 1 GiB), threads 4 (1 to 16), salt_length 16 (8 to 64), key_length 32 (16 to 128); out-of-range values fail Open. Plaintext over 1024 bytes returns ErrPasswordTooLong. See the password reference.

login.go
pw, err := c.Password()
if err != nil {
return err
}
hash, err := pw.Hash(ctx, "correct horse battery staple")
if err != nil {
return err
}
ok, err := pw.Verify(ctx, hash, "correct horse battery staple")
if err != nil {
return err
}
rehash, err := pw.NeedsRehash(ctx, hash)
hash: $argon2id$v=19$m=65536,t=3,p=4$<salt>$<key>
ok: true
rehash: false (true after a cost-parameter bump)

Stored form is PHC; salts come from crypto/rand, comparison is constant-time. Verify returns true, nil (match), false, nil (mismatch, reject generically), or _, ErrInvalidHash (corrupt, force reset); check the sentinel with errors.Is.

  1. Benchmark on production-class hardware; a laptop number can be too cheap.
  2. Deploy; old hashes keep verifying.
  3. NeedsRehash flags stale hashes per login; rehash and persist.
  4. Track the stale count to zero.
  • Hashing cost does not limit attempts; rate-limit login (Rate limiting).
  • Never log passwords or hashes; errors name the failure, not the value.
ErrInvalidHash on a known account

Stored value truncated or corrupted. Confirm with errors.Is, force a reset.

Logins slow to a crawl

Cost parameters exceed fleet capacity. Benchmark, lower toward defaults, scale out first.

NeedsRehash is true for every user

Parameters changed since minting. Rehash on each account’s next successful login.

Password rejected for length

Plaintext exceeds 1024 bytes. Reject at the boundary before hashing.

Authentication · Rate limiting