Help us shape the future of Go! Take the 2026 Go Developer Survey

password

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package password provides bounded Argon2id hashing and verification. Hashes and plaintext remain distinct redacted values. Login eligibility, throttling, MFA and credential issuance belong to the model-first authentication flow.

Index

Constants

View Source
const (
	MaxPasswordBytes        = 4096
	MaxEncodedBytes         = 512
	MaxMemoryKiB     uint32 = 1024 * 1024
	MaxIterations    uint32 = 16
	MaxParallelism   uint8  = 16
	SaltBytes               = 16
	KeyBytes                = 32
)

Variables

This section is empty.

Functions

func Codec

func Codec() codec.Codec[Hash]

Codec is the shared generated-model persistence boundary. PostgreSQL stores canonical PHC text; Go queries, drafts and hydration retain Hash. A plain or malformed string never becomes a hash by an implicit conversion. SQL NULL requires value.Nullable[Hash]. Automatic audit/cursor/identity disclosure is disabled by the codec, independently of the column's name.

Types

type Config

type Config struct {
	Parameters  Parameters
	VerifyLimit Parameters
	// MaxBcryptCost bounds verification of imported bcrypt hashes; each step
	// doubles the work (12 is roughly 250ms). Zero rejects bcrypt hashes.
	MaxBcryptCost int
	MaxConcurrent int
	Timeout       time.Duration
}

Config sets issuance costs and separate verification ceilings for existing hashes. At most MaxConcurrent KDFs run, each bounded by VerifyLimit.MemoryKiB. Each running Argon2 check allocates its hash's memory cost: 64 MiB with the default Parameters, up to VerifyLimit.MemoryKiB (128 MiB by default) for stored legacy hashes. The default of 4 therefore bounds KDF memory to about 256 MiB (512 MiB worst case); size it to the instance's memory budget. Excess requests queue for at most min(Timeout, 5s), then fail with fault.Overloaded (HTTP 503) before any KDF work starts. Timeout cancels admission/publication; a started KDF owns its slot until exit because Argon2 has no cooperative cancellation. No background hash is abandoned.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns default Argon2id parameters, verification ceilings, bcrypt ceiling and admission bounds.

func (Config) Validate

func (c Config) Validate() error

Validate checks hash strength, verification ceilings, bcrypt cost and operation bounds.

type Hash

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

Hash is a validated, bounded Argon2id PHC value. It is distinct from plaintext and redacts ordinary formatting/JSON. Encoded is the explicit persistence or migration boundary. Hash has no JSONContract: it is not a public response field. Imported Argon2i PHC and bcrypt ($2a$/$2b$/$2y$, for example from Laravel) hashes are accepted for verification only; NeedsRehash reports them so a successful login replaces them with Argon2id.

func ParseHash

func ParseHash(encoded secret.String) (Hash, error)

ParseHash validates a supported Argon2 or bcrypt encoding without verifying a password.

func (Hash) Encoded

func (h Hash) Encoded() secret.String

Encoded exposes the secret hash wrapper for persistence or migration.

func (Hash) Format

func (Hash) Format(s fmt.State, _ rune)

Format writes the redaction marker without exposing the value.

func (Hash) LogValue

func (Hash) LogValue() slog.Value

LogValue returns the redaction marker without exposing the value.

func (Hash) MarshalJSON

func (Hash) MarshalJSON() ([]byte, error)

MarshalJSON encodes the redaction marker without exposing the value.

func (*Hash) Scan

func (h *Hash) Scan(source any) error

Scan changes the destination only after a complete valid PHC decode.

func (Hash) Validate

func (h Hash) Validate() error

Validate checks the stored hash encoding without verifying a password.

func (Hash) Value

func (h Hash) Value() (driver.Value, error)

Value is an explicit database/sql persistence boundary, not a display value.

type Hasher

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

Hasher owns bounded CPU/memory admission. Share one instance across the application's login/reset paths. It owns no database, models or goroutines between operations; constructing it performs no hashing or other I/O.

func New

func New(config Config) (*Hasher, error)

New validates config and creates a hasher with bounded operation admission.

func (*Hasher) Check

func (h *Hasher) Check(ctx context.Context, plain Plaintext, hash Hash) (bool, error)

Check compares derived keys in constant time. A mismatch is false with no error; malformed/unsupported hashes and resource-ceiling violations are errors. Login adapters must expose one unauthenticated response without disclosing which condition occurred. Bounds are checked before allocating Argon2 memory.

func (*Hasher) DummyCheck

func (h *Hasher) DummyCheck(ctx context.Context, plain Plaintext) error

DummyCheck consumes the current issuance policy's verification work for a missing or unusable credential. It discards the comparison result and grants no authority. Login orchestration uses it to avoid a cheap missing-account branch. Different legacy costs and database latency still affect timing; this is not a claim of constant-time account discovery protection.

func (*Hasher) Hash

func (h *Hasher) Hash(ctx context.Context, plain Plaintext) (Hash, error)

Hash uses a fresh random salt and the configured issuance policy. Error or cancellation returns zero Hash, including when the KDF finishes after timeout.

func (*Hasher) NeedsRehash

func (h *Hasher) NeedsRehash(hash Hash) (bool, error)

NeedsRehash reports divergence from this explicit issuance policy; it does not authenticate the input or write a replacement. Call only after successful Check and update using a compare-and-swap on the original stored hash. Changing policy may increase or decrease costs; choose it deliberately for deployment.

func (*Hasher) Validate

func (h *Hasher) Validate() error

Validate checks that the hasher is configured and its policy is valid.

type Parameters

type Parameters struct {
	MemoryKiB   uint32
	Iterations  uint32
	Parallelism uint8
}

Parameters measures memory in KiB and iterations in passes. These values affect resource use, not password validation rules. No implicit normalization or truncation is performed. ParseHash accepts bounded older costs; new hashing requires at least 19 MiB and two passes, with 64 MiB/three passes the default.

func (Parameters) Validate

func (p Parameters) Validate() error

Validate checks supported memory, iteration and parallelism bounds.

type Plaintext

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

Plaintext is a bounded password input, never a persisted hash. Its JSON decoder preserves exact input bytes; output/logging redacts it. Creation does not enforce an application's password-strength policy or verify credentials.

func NewPlaintext

func NewPlaintext(raw secret.String) (Plaintext, error)

NewPlaintext requires nonempty password input no longer than MaxPasswordBytes.

func (Plaintext) Format

func (Plaintext) Format(s fmt.State, _ rune)

Format writes the redaction marker without exposing the value.

func (Plaintext) JSONContract

func (Plaintext) JSONContract() contract.JSON[Plaintext]

JSONContract allows a generated login/request DTO to discover this input's wire string shape without exposing the private Go representation.

func (Plaintext) LogValue

func (Plaintext) LogValue() slog.Value

LogValue returns the redaction marker without exposing the value.

func (Plaintext) MarshalJSON

func (Plaintext) MarshalJSON() ([]byte, error)

MarshalJSON encodes the redaction marker without exposing the value.

func (Plaintext) Secret

func (p Plaintext) Secret() secret.String

Secret explicitly exposes the input for domain strength validation or a credential adapter. The returned secret still redacts ordinary serialization.

func (*Plaintext) UnmarshalJSON

func (p *Plaintext) UnmarshalJSON(data []byte) error

UnmarshalJSON clears the receiver and decodes a nonempty, bounded password string.

func (Plaintext) Validate

func (p Plaintext) Validate() error

Validate checks the password's nonempty input and byte bound.

Jump to

Keyboard shortcuts

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