argon2id

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 8 Imported by: 0

README

deps.dev Go Reference License Stay with Ukraine

argon2id

argon2id hashes and verifies passwords with Argon2id (RFC 9106), the memory-hard function chosen by the Password Hashing Competition. Memory-hard means computing a hash costs a defined amount of RAM, which is what makes offline GPU and ASIC cracking of a leaked hash expensive - the property a password hasher exists to provide.

Argon2id is built on BLAKE2b (RFC 7693), which the standard library does not ship, so this package implements both from scratch on the standard library alone. It has zero dependencies and its output is pinned to the official RFC test vectors.

Features

  • Memory-hard by design - Argon2id, the hybrid recommended for password storage, resisting both side-channel and time-memory-trade-off attacks.
  • Self-describing hashes - a standard PHC string carries the algorithm, version, cost parameters and salt, so Verify needs nothing but the string.
  • Tunable cost - memory, passes and parallelism as functional options, with sane defaults and bounds that reject a hostile or malformed hash before it can allocate memory.
  • Rehash on login - NeedsRehash reports when a stored hash is weaker than your current settings, so you can transparently upgrade it.
  • Zero dependencies - standard library only; no cgo, no third-party code.
  • Pinned to the spec - validated against the RFC 9106 Argon2id vector and the RFC 7693 BLAKE2b vectors.

Installation

go get github.com/goloop/argon2id

Requires Go 1.24 or newer. The package has no third-party dependencies.

Quick start

h := argon2id.New()

encoded, err := h.Hash([]byte(password)) // store encoded (a string)
if err != nil {
	// only fails if the system CSPRNG fails
}

err = h.Verify(encoded, []byte(attempt)) // nil on match
if errors.Is(err, argon2id.ErrMismatch) {
	// wrong password
}

The encoded value is a PHC string that stands on its own:

$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHR2YWx1ZQ$aGFzaGRpZ2VzdC4uLg

Store it as-is. Verify reads the parameters and salt back out of it, so you never manage them separately.

Tuning the cost

The defaults - 64 MiB of memory, two passes, one lane - suit an interactive login on modest hardware. Raise them for higher-value secrets or faster hardware; the right numbers depend on your latency budget, so measure.

h := argon2id.New(
	argon2id.WithMemory(128*1024), // KiB (128 MiB)
	argon2id.WithTime(3),          // passes over memory
	argon2id.WithThreads(4),       // lanes (parallelism)
)

Every option is bounded: values are clamped to a safe range so a hasher can never be configured to mint a hash its own Verify would later reject.

Upgrading old hashes

Call NeedsRehash after a successful Verify to raise the cost of stored hashes as your defaults strengthen over time:

if err := h.Verify(stored, pw); err == nil {
	if h.NeedsRehash(stored) {
		fresh, _ := h.Hash(pw) // persist fresh in place of stored
	}
}

Use with goloop/auth

The Hasher method set (Hash, Verify, NeedsRehash) matches the PasswordHasher and Rehasher interfaces in goloop/auth, so it drops in wherever those are expected - without either package importing the other:

var hasher auth.PasswordHasher = argon2id.New()

Use goloop/auth for tokens, refresh rotation and middleware, and this package for the password hash underneath.

Correctness

Password hashing is one place where a subtle bug is silent, so the implementation is checked against published test vectors:

  • Argon2id - the RFC 9106 vector (password, salt, secret and associated data).
  • BLAKE2b - the RFC 7693 vectors.

If those pass, the construction matches the reference bit for bit. Run them with go test ./....

License

MIT - see LICENSE.

Documentation

Overview

Package argon2id hashes and verifies passwords with Argon2id (RFC 9106).

Argon2id is memory-hard: computing a hash costs a defined amount of RAM, which is what makes offline GPU and ASIC cracking of a leaked hash expensive. Argon2 is built on BLAKE2b (RFC 7693), which the standard library does not ship, so this package implements both from scratch on the standard library alone. It has no third-party dependencies and its output is pinned to the official RFC test vectors.

Hashing

h := argon2id.New()
encoded, err := h.Hash([]byte(password)) // store encoded (a string)
err = h.Verify(encoded, []byte(attempt)) // nil on match

The encoded value is a self-describing PHC string ($argon2id$v=19$m=...,t=...,p=...$salt$digest): it carries the algorithm, version, cost parameters and salt, so Verify needs nothing but the string.

Cost

h := argon2id.New(
    argon2id.WithMemory(128*1024), // KiB
    argon2id.WithTime(3),          // passes
    argon2id.WithThreads(4),       // lanes
)

The defaults (64 MiB, two passes, one lane) suit an interactive login on modest hardware. Every option is bounded, so a hasher can never be configured to mint a hash its own Verify would reject.

Rehashing

if err := h.Verify(stored, pw); err == nil {
    if h.NeedsRehash(stored) {
        fresh, _ := h.Hash(pw) // persist fresh in place of stored
    }
}

NeedsRehash reports when a stored hash is weaker than the current settings, so a successful login can transparently upgrade it as defaults strengthen.

Interop

The Hasher method set (Hash, Verify, NeedsRehash) matches the PasswordHasher and Rehasher interfaces in goloop/auth, so it can be used through them without either package importing the other.

See DOC.md (English) and DOC.UK.md (Ukrainian) for the full reference.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMismatch is returned when a password does not match its hash.
	ErrMismatch = errors.New("argon2id: password mismatch")

	// ErrInvalidHash is returned when an encoded hash is malformed or its
	// parameters fall outside the accepted bounds.
	ErrInvalidHash = errors.New("argon2id: invalid hash")
)

Errors returned by Verify.

Functions

This section is empty.

Types

type Hasher

type Hasher struct {
	// contains filtered or unexported fields
}

Hasher hashes and verifies passwords with Argon2id.

func New

func New(opts ...Option) *Hasher

New returns an Argon2id Hasher configured by opts.

func (*Hasher) Hash

func (h *Hasher) Hash(password []byte) (string, error)

Hash returns a PHC-encoded Argon2id hash: $argon2id$v=19$m=<memory>,t=<time>,p=<threads>$<salt>$<digest>.

func (*Hasher) NeedsRehash

func (h *Hasher) NeedsRehash(encoded string) bool

NeedsRehash reports whether encoded should be replaced: true for a malformed hash, or one whose memory, time, parallelism, salt or key length is below this hasher's current settings. Call it after a successful Verify to upgrade stored hashes as defaults strengthen over time.

func (*Hasher) Verify

func (h *Hasher) Verify(encoded string, password []byte) error

Verify checks password against an encoded Argon2id hash in constant time. A hash whose parameters fall outside the verification bounds is rejected as invalid before any key derivation runs.

type Option

type Option func(*Hasher)

Option configures New.

func WithKeyLength

func WithKeyLength(n int) Option

WithKeyLength sets the derived digest length in bytes, clamped to 16..128.

func WithMemory

func WithMemory(kib int) Option

WithMemory sets the memory cost in KiB. Non-positive values are ignored; the value is capped at the verification ceiling.

func WithSaltLength

func WithSaltLength(n int) Option

WithSaltLength sets the random salt length in bytes, clamped to 8..64.

func WithThreads

func WithThreads(lanes int) Option

WithThreads sets the number of lanes (parallelism), clamped to 1..255.

func WithTime

func WithTime(passes int) Option

WithTime sets the number of passes over memory. Non-positive values are ignored; the value is capped at the verification ceiling.

Jump to

Keyboard shortcuts

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