Documentation
¶
Overview ¶
Package pass provides multi-scheme password hashing with transparent migration support. Argon2id is the default; bcrypt is accepted for migration from existing stores. Django's "argon2$argon2id$..." hash format is also supported.
Typical login flow:
pc := pass.NewDefaultContext()
if err := pc.Verify(stored, input); err != nil {
return err
}
if pc.NeedsUpdate(stored) {
if newHash, err := pc.Hash(input); err == nil {
_ = db.UpdatePasswordHash(ctx, userID, newHash)
}
}
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrMismatch = errors.New("password does not match")
ErrMismatch is returned by Verify when the password does not match the hash.
var ErrUnknownHash = errors.New("unrecognized hash format")
ErrUnknownHash is returned by Verify when no registered hasher recognizes the hash format.
var RFC9106HighMemory = Argon2id{
Memory: 1 << 21,
Iterations: 1,
Parallelism: 4,
KeyLen: 32,
SaltLen: 16,
}
RFC9106HighMemory is the Argon2id parameter set from RFC 9106's first recommendation, for environments where memory is not at a premium.
var RFC9106LowMemory = Argon2id{
Memory: 1 << 16,
Iterations: 3,
Parallelism: 4,
KeyLen: 32,
SaltLen: 16,
}
RFC9106LowMemory is the Argon2id parameter set from RFC 9106's second recommendation, for environments where memory is constrained to ~64 MiB. This is the default used by pass.Default.
Functions ¶
This section is empty.
Types ¶
type Argon2id ¶
type Argon2id struct {
Memory uint32 // kibibytes; 0 uses default (65536)
Iterations uint32 // 0 uses default (1)
Parallelism uint8 // 0 uses default (runtime.NumCPU())
KeyLen uint32 // 0 uses default (32)
SaltLen uint32 // 0 uses default (16)
}
Argon2id hashes passwords using the argon2id algorithm. The zero value uses the defaults from github.com/alexedwards/argon2id (64 MiB memory, 1 iteration, runtime.NumCPU() parallelism, 32-byte key, 16-byte salt).
Django's "argon2$argon2id$..." hash format is accepted for verification and always triggers NeedsUpdate so hashes are migrated to the canonical format on next login.
func (Argon2id) Identify ¶
Identify reports whether hash was produced by argon2id, including Django's "argon2$argon2id$..." format.
func (Argon2id) NeedsUpdate ¶
NeedsUpdate reports whether hash should be rehashed. Returns true for Django-format hashes (to migrate to canonical format) or if the stored parameters differ from the current configuration.
type Bcrypt ¶
type Bcrypt struct {
Cost int // 0 uses bcrypt.DefaultCost
MinCost int // 0 uses Cost; hashes below this trigger NeedsUpdate
}
Bcrypt hashes passwords using bcrypt. The zero value uses bcrypt.DefaultCost (10) for both hashing and the minimum acceptable cost.
func (Bcrypt) NeedsUpdate ¶
NeedsUpdate reports whether hash was hashed with a cost below MinCost.
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context holds an ordered list of hashers. The first hasher is the default for new hashes; the rest are accepted for verification but treated as deprecated (NeedsUpdate returns true for any hash they identify).
func NewContext ¶
NewContext returns a Context using the given hashers. The first hasher is used for new hashes; remaining hashers are treated as deprecated.
func NewDefaultContext ¶
func NewDefaultContext() *Context
NewDefaultContext returns a Context suitable for most applications. Outside of tests it uses RFC 9106 low-memory Argon2id as the primary hasher with bcrypt accepted for migration. Under go test it delegates to NewTestContext so that test suites do not pay full hashing costs.
func NewTestContext ¶
func NewTestContext() *Context
NewTestContext returns a Context with minimal-cost hashers for use in tests. The parameters are intentionally weak — do not use in production.
func (*Context) DummyVerify ¶
DummyVerify performs a full hash verification against a pre-computed dummy hash to prevent timing-based user enumeration. Call it in the "user not found" branch of your authentication flow so that missing-user lookups take the same time as wrong-password lookups:
user, err := db.GetUser(ctx, username)
if errors.Is(err, db.ErrNotFound) {
pass.DummyVerify(password)
return ErrInvalidCredentials
}
The dummy hash is computed lazily on the first call using the default hasher's parameters.
func (*Context) NeedsUpdate ¶
NeedsUpdate reports whether hash should be rehashed. Returns true if the hash belongs to a non-default hasher or if the default hasher's own NeedsUpdate reports true.
type Hasher ¶
type Hasher interface {
// Hash produces an encoded hash string for password.
Hash(password string) (string, error)
// Verify checks password against hash. Returns ErrMismatch on wrong
// password or ErrUnknownHash if the format is not recognized.
Verify(hash, password string) error
// Identify reports whether this hasher produced hash.
Identify(hash string) bool
// NeedsUpdate reports whether hash should be rehashed with current
// parameters.
NeedsUpdate(hash string) bool
}
Hasher is implemented by each supported password hashing algorithm.