password

package
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Mar 15, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package password provides Argon2id password hashing for authcore.

Why Argon2id?

Argon2id is the algorithm recommended by OWASP and RFC 9106 for password storage. Unlike bcrypt, it is memory-hard: an attacker must allocate large amounts of RAM per attempt, making GPU and ASIC brute-force attacks prohibitively expensive.

Zero-config setup

The OWASP-recommended defaults work out of the box — no configuration needed:

auth, _   := authcore.New(authcore.DefaultConfig())
pwdMod, _ := password.New(auth) // ← that's it

What is fixed (security guarantees you get for free)

  • Algorithm: Argon2id (RFC 9106) — always
  • Salt: 16 random bytes per hash — via crypto/rand
  • Key length: 32 bytes (256-bit output)
  • Output: PHC string format — self-describing, portable
  • Comparison: constant-time — immune to timing attacks
  • Policy: Hash rejects weak passwords before spending CPU on them

What is tunable

Memory, Iterations, and Parallelism can be increased to match your hardware. The algorithm and output format are never configurable — that's the point.

Full usage

// Startup — one instance, shared across all goroutines.
auth, _   := authcore.New(authcore.DefaultConfig())
pwdMod, _ := password.New(auth)

// Registration — hash and store. Never store the plaintext.
hash, err := pwdMod.Hash(userPassword)
db.StorePasswordHash(userID, hash)

// Login — verify in constant time.
ok, err := pwdMod.Verify(submittedPassword, storedHash)
if !ok { return http.StatusUnauthorized }

// Password change — verify first, then hash the new one.
ok, _ = pwdMod.Verify(currentPassword, storedHash)
if !ok { return http.StatusUnauthorized }
newHash, _ := pwdMod.Hash(newPassword)
db.UpdatePasswordHash(userID, newHash)

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidConfig = errors.New("password: invalid config")

ErrInvalidConfig is returned by New when the provided Config fails validation.

View Source
var ErrInvalidHash = errors.New("password: invalid hash format")

ErrInvalidHash is returned by Verify when the stored hash is not a valid Argon2id PHC string produced by this module.

View Source
var ErrWeakPassword = errors.New("password: does not meet policy requirements")

ErrWeakPassword is returned by Hash when the plaintext password does not satisfy the built-in policy. Wrap-check with errors.Is; inspect the message for the specific requirement that failed.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Memory is the amount of memory used by Argon2id, in kibibytes.
	// Higher values increase resistance to GPU/ASIC brute-force attacks.
	// Defaults to 65536 (64 MiB). Minimum 8192 (8 MiB).
	Memory uint32

	// Iterations is the number of passes Argon2id makes over the memory.
	// Higher values increase the CPU cost per hash without changing memory use.
	// Defaults to 3. Minimum 1.
	Iterations uint32

	// Parallelism is the number of threads Argon2id uses.
	// Set this to the minimum number of CPU cores guaranteed to your service.
	// Defaults to 2. Minimum 1.
	Parallelism uint8

	// DisablePolicy disables the built-in password policy check inside Hash.
	//
	// By default, Hash rejects any password that does not satisfy all of:
	//   - Between 12 and 64 characters
	//   - At least one uppercase letter
	//   - At least one lowercase letter
	//   - At least one digit
	//   - At least one special character (anything that is not a letter or digit)
	//
	// Set DisablePolicy to true only when you apply your own validation before
	// calling Hash, or when migrating legacy password hashes.
	DisablePolicy bool
}

Config holds the password module configuration.

Only the Argon2id work parameters are tunable — Memory, Iterations, and Parallelism. The algorithm (Argon2id), salt size (16 bytes), and key size (32 bytes) are fixed to enforce consistent security across all deployments.

Start from DefaultConfig and override only what your hardware supports:

cfg := password.DefaultConfig()
cfg.Memory      = 128 * 1024  // 128 MiB — for a dedicated auth server
cfg.Iterations  = 4
cfg.Parallelism = 4           // match your guaranteed CPU core count
pwdMod, err := password.New(auth, cfg)

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with OWASP-recommended Argon2id defaults.

The defaults are calibrated for a server with at least 2 vCPUs and 4 GiB of RAM. Each Hash call temporarily allocates Memory kibibytes (64 MiB) of RAM. Tune Memory and Iterations upward on more capable hardware to strengthen the work factor over time.

type Password

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

Password is the authentication module for Argon2id password hashing.

Construct one instance at application startup using New and share it across goroutines. Password is safe for concurrent use after construction.

func New

func New(p authcore.Provider, cfg ...Config) (*Password, error)

New creates and returns a Password module.

cfg is optional — omit it to use the OWASP-recommended defaults (Argon2id, 64 MiB, 3 iterations, 2 threads). Pass a Config only when you need to tune the work parameters for your hardware:

// zero-config — safe defaults, no boilerplate
pwdMod, err := password.New(auth)

// custom work factor for a more powerful server
pwdMod, err := password.New(auth, password.Config{
    Memory:      128 * 1024,
    Iterations:  4,
    Parallelism: 4,
})

func (*Password) Hash

func (p *Password) Hash(plaintext string) (string, error)

Hash validates plaintext against the built-in password policy and, if it passes, derives an Argon2id hash returned in PHC string format. A fresh cryptographically random salt is generated per call, so two calls with the same input produce different (but equivalent) hashes.

Policy (enforced by default, disable via Config.DisablePolicy):

  • 12–64 characters
  • At least one uppercase letter, one lowercase letter, one digit, one special character

Store the returned string in your database. Never store the plaintext password.

hash, err := pwdMod.Hash(userPassword)
if errors.Is(err, password.ErrWeakPassword) { /* tell the user what's wrong */ }
db.StorePasswordHash(userID, hash)

func (*Password) Name

func (p *Password) Name() string

Name returns the module's unique identifier. It implements authcore.Module.

func (*Password) ValidatePolicy added in v1.1.1

func (p *Password) ValidatePolicy(plaintext string) error

ValidatePolicy reports whether plaintext satisfies the built-in password policy. Use this for fail-fast validation before calling Hash — for example, in an HTTP handler to return a 400 before spending CPU on Argon2id.

Returns nil if the password is acceptable, or a descriptive ErrWeakPassword wrapping the specific rule that was violated.

This check is identical to the one Hash performs internally unless DisablePolicy is set to true in the module config.

func (*Password) Verify

func (p *Password) Verify(plaintext, phcHash string) (bool, error)

Verify reports whether plaintext matches the Argon2id hash in phcHash.

The Argon2id parameters (Memory, Iterations, Parallelism) are read from phcHash itself, so stored hashes remain valid even if the module's Config is updated after they were created.

The comparison is performed in constant time to prevent timing attacks.

ok, err := pwdMod.Verify(submittedPassword, storedHash)
if errors.Is(err, password.ErrInvalidHash) { ... } // hash is malformed
if !ok { return http.StatusUnauthorized }

Jump to

Keyboard shortcuts

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