41 lines
1.4 KiB
Go
41 lines
1.4 KiB
Go
// Package auth holds the cryptographic adapters — password hashing and JWT
|
|
// signing/verification. They implement use-case ports and keep bcrypt and the
|
|
// JWT library out of the domain and use-case layers.
|
|
package auth
|
|
|
|
import "golang.org/x/crypto/bcrypt"
|
|
|
|
// Hasher turns plaintext passwords into storable hashes and checks them back.
|
|
type Hasher struct {
|
|
cost int
|
|
}
|
|
|
|
// NewHasher builds a Hasher. A cost of 0 uses bcrypt's default work factor.
|
|
func NewHasher(cost int) Hasher {
|
|
if cost == 0 {
|
|
cost = bcrypt.DefaultCost
|
|
}
|
|
return Hasher{cost: cost}
|
|
}
|
|
|
|
// Hash returns the bcrypt hash of password. The salt and the cost are embedded
|
|
// in the returned string, so nothing else needs to be stored alongside it.
|
|
//
|
|
// bcrypt silently ignores input past 72 bytes; the use case rejects longer
|
|
// passwords before reaching here so a truncated tail never becomes a security
|
|
// surprise.
|
|
func (h Hasher) Hash(password string) (string, error) {
|
|
b, err := bcrypt.GenerateFromPassword([]byte(password), h.cost)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(b), nil
|
|
}
|
|
|
|
// Compare reports whether password matches the stored hash. It returns a
|
|
// non-nil error (bcrypt.ErrMismatchedHashAndPassword) on any mismatch, which
|
|
// the caller collapses into a generic authentication failure.
|
|
func (h Hasher) Compare(hash, password string) error {
|
|
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
}
|