package webapp import ( "fmt" "golang.org/x/crypto/bcrypt" ) // bcryptCost is the work factor for new bcrypt hashes. Matches the // "cost 12" assumption from docs/distributed/worker-web-app.md // section 5.2; the cost applies to first-run and password-change // hashes alike. const bcryptCost = 12 // HashPassword bcrypts the given plaintext password at the package's // configured cost. Returns the encoded hash ready to be persisted. func HashPassword(plain string) (string, error) { if plain == "" { return "", fmt.Errorf("webapp: empty password") } h, err := bcrypt.GenerateFromPassword([]byte(plain), bcryptCost) if err != nil { return "", fmt.Errorf("webapp: bcrypt hash: %w", err) } return string(h), nil } // VerifyPassword reports whether the given plaintext matches the // given bcrypt hash. A nil error means the password is correct. func VerifyPassword(hash, plain string) error { return bcrypt.CompareHashAndPassword([]byte(hash), []byte(plain)) } // MaskToken returns the last 4 characters of a token prefixed with a // star mask, e.g. "****abcd". Empty input yields "—". Used on the // settings page where the worker's bearer token is shown read-only. func MaskToken(token string) string { if token == "" { return "—" } if len(token) <= 4 { return "****" } return "****" + token[len(token)-4:] }