gofiber/fiber · error
decode SHA256 password
Error message
decode SHA256 password: %w
What it means
Returned by parseHashedPassword when a '{SHA256}'-prefixed password string cannot be base64-decoded. Same shape as the SHA512 case but for the 32-byte SHA-256 digest path. The {SHA256} prefix is what Apache's htpasswd emits for SHA-256, so mis-serialized htpasswd entries are the most common cause.
Solutions
- Regenerate with standard base64 of the raw 32-byte SHA-256 digest.
- Verify with htpasswd -vb that the entry is well-formed before pasting.
- Strip whitespace and confirm exactly one '='-padded token follows {SHA256}.
- Ensure the decoded length is 32 bytes (sha256.Size) to avoid the next guard's ErrInvalidSHA256PasswordLength.
- Quote the value in YAML/JSON to prevent '+/=' interpretation.
Example fix
// before
"{SHA256}" + strings.ReplaceAll(stdB64, "+", "-") // accidentally URL-safe
// after
"{SHA256}" + base64.StdEncoding.EncodeToString(sum[:]) Defensive patterns
Strategy: validation
Validate before calling
func validateSHA256Hash(h string) error {
if !strings.HasPrefix(h, "{SHA256}") { return nil }
b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(h, "{SHA256}"))
if err != nil { return fmt.Errorf("bad SHA256 base64: %w", err) }
if len(b) != sha256.Size { return fmt.Errorf("SHA256 digest must be %d bytes, got %d", sha256.Size, len(b)) }
return nil
} Prevention
- Generate digests with standard base64 of the raw 32-byte SHA-256 sum.
- Verify htpasswd -s entries before pasting into config.
- Quote credential strings in YAML to protect '+/=' characters.
- Run an init-time validator over the Users map.
When it happens
Trigger: Users map value is '{SHA256}<not-base64>': bad characters, URL-safe alphabet, missing padding, or trailing newline. Frequently seen when migrating entries from Apache htpasswd that were re-encoded or truncated.
Common situations: htpasswd -s output pasted with a trailing newline; secret manager base64'd the already-base64 value; encoding alphabet mismatch (URL-safe vs standard); YAML loader that interpreted '+/=' as special.
Related errors
- decode SHA512 password
- basicauth: charset must be UTF-8
- decode SHA256 password: invalid length
- failed to base64-decode key
- add: invalid http method
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/2e507eed61a54cc6.
Report an issue: GitHub.
Appendix: source
Thrown at middleware/basicauth/config.go:288
case strings.HasPrefix(h, "{SHA512}"):
b, err := base64.StdEncoding.DecodeString(h[len("{SHA512}"):])
if err != nil {
return nil, fmt.Errorf("decode SHA512 password: %w", err)
}
// A digest of the wrong size can never equal a SHA-512 sum, so
// accepting it would silently reject every password for this user.
// Report it instead, which surfaces as a panic at startup.
if len(b) != sha512.Size {
return nil, ErrInvalidSHA512PasswordLength
}
return func(p string) bool {
sum := sha512.Sum512([]byte(p))
return subtle.ConstantTimeCompare(sum[:], b) == 1
}, nil
case strings.HasPrefix(h, "{SHA256}"):
b, err := base64.StdEncoding.DecodeString(h[len("{SHA256}"):])
if err != nil {
return nil, fmt.Errorf("decode SHA256 password: %w", err)
}
if len(b) != sha256.Size {
return nil, ErrInvalidSHA256PasswordLength
}
return func(p string) bool {
sum := sha256.Sum256([]byte(p))
return subtle.ConstantTimeCompare(sum[:], b) == 1
}, nil
default:
b, err := hex.DecodeString(h)
if err != nil || len(b) != sha256.Size {
if b, err = base64.StdEncoding.DecodeString(h); err != nil {
return nil, fmt.Errorf("decode SHA256 password: %w", err)
}
if len(b) != sha256.Size {
return nil, ErrInvalidSHA256PasswordLength
}
}View on GitHub (pinned to a105acad6c)