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
- func Codec() codec.Codec[Hash]
- type Config
- type Hash
- type Hasher
- func (h *Hasher) Check(ctx context.Context, plain Plaintext, hash Hash) (bool, error)
- func (h *Hasher) DummyCheck(ctx context.Context, plain Plaintext) error
- func (h *Hasher) Hash(ctx context.Context, plain Plaintext) (Hash, error)
- func (h *Hasher) NeedsRehash(hash Hash) (bool, error)
- func (h *Hasher) Validate() error
- type Parameters
- type Plaintext
- func (Plaintext) Format(s fmt.State, _ rune)
- func (Plaintext) JSONContract() contract.JSON[Plaintext]
- func (Plaintext) LogValue() slog.Value
- func (Plaintext) MarshalJSON() ([]byte, error)
- func (p Plaintext) Secret() secret.String
- func (p *Plaintext) UnmarshalJSON(data []byte) error
- func (p Plaintext) Validate() error
Constants ¶
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 ¶
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.
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 ¶
ParseHash validates a supported Argon2 or bcrypt encoding without verifying a password.
func (Hash) MarshalJSON ¶
MarshalJSON encodes the redaction marker without exposing the 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 (*Hasher) Check ¶
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 ¶
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 ¶
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 ¶
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.
type Parameters ¶
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 ¶
NewPlaintext requires nonempty password input no longer than MaxPasswordBytes.
func (Plaintext) JSONContract ¶
JSONContract allows a generated login/request DTO to discover this input's wire string shape without exposing the private Go representation.
func (Plaintext) MarshalJSON ¶
MarshalJSON encodes the redaction marker without exposing the value.
func (Plaintext) Secret ¶
Secret explicitly exposes the input for domain strength validation or a credential adapter. The returned secret still redacts ordinary serialization.
func (*Plaintext) UnmarshalJSON ¶
UnmarshalJSON clears the receiver and decodes a nonempty, bounded password string.