{"record":{"id":"373f1aada4c9e135","repo":"gofiber/fiber","slug":"decode-sha512-password-w","errorCode":null,"errorMessage":"decode SHA512 password: %w","messagePattern":"decode SHA512 password: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/basicauth/config.go","lineNumber":273,"sourceCode":"func (s verifierStrength) betterThan(other verifierStrength) bool {\n\tif s.algorithm != other.algorithm {\n\t\treturn s.algorithm > other.algorithm\n\t}\n\n\treturn s.cost > other.cost\n}\n\nfunc parseHashedPassword(h string) (passwordVerifier, error) {\n\tswitch {\n\tcase strings.HasPrefix(h, \"$2\"):\n\t\thash := []byte(h)\n\t\treturn func(p string) bool {\n\t\t\treturn bcrypt.CompareHashAndPassword(hash, []byte(p)) == nil\n\t\t}, nil\n\tcase strings.HasPrefix(h, \"{SHA512}\"):\n\t\tb, err := base64.StdEncoding.DecodeString(h[len(\"{SHA512}\"):])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decode SHA512 password: %w\", err)\n\t\t}\n\t\t// A digest of the wrong size can never equal a SHA-512 sum, so\n\t\t// accepting it would silently reject every password for this user.\n\t\t// Report it instead, which surfaces as a panic at startup.\n\t\tif len(b) != sha512.Size {\n\t\t\treturn nil, ErrInvalidSHA512PasswordLength\n\t\t}\n\t\treturn func(p string) bool {\n\t\t\tsum := sha512.Sum512([]byte(p))\n\t\t\treturn subtle.ConstantTimeCompare(sum[:], b) == 1\n\t\t}, nil\n\tcase strings.HasPrefix(h, \"{SHA256}\"):\n\t\tb, err := base64.StdEncoding.DecodeString(h[len(\"{SHA256}\"):])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decode SHA256 password: %w\", err)\n\t\t}\n\t\tif len(b) != sha256.Size {\n\t\t\treturn nil, ErrInvalidSHA256PasswordLength","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/basicauth/config.go#L255-L291","documentation":"Returned by parseHashedPassword in the basicauth middleware when a password string prefixed with '{SHA512}' cannot be base64-decoded. The prefix tells Fiber the remainder is a base64-encoded SHA-512 digest; base64.StdEncoding.DecodeString returns an error for bad padding, illegal characters, or wrong length. The error propagates up and surfaces as a panic at app construction because invalid credentials are a configuration defect, not a runtime condition.","triggerScenarios":"Users/Passwords map has a value like '{SHA512}<garbage>' where the part after the prefix is not valid standard base64: truncated, URL-safe base64 (- and _) instead of (+ and /), missing padding, or contains whitespace/newlines copied from a terminal.","commonSituations":"Operator generated the digest with base64.URLEncoding instead of StdEncoding; copy-paste lost trailing '=' padding; secret was rotated through a YAML/JSON loader that stripped characters; CI pipeline encoded with `base64 -w0` on a system whose default differs; trailing newline from echo included in the value.","solutions":["Regenerate with standard encoding: printf '%s' \"$pw\" | sha512sum | awk '{print $1}' | xxd -r -p | base64, then prefix {SHA512}.","Strip whitespace/newlines before storing: tr -d ' \\n' on the value.","If you have URL-safe base64, re-encode to standard: replace - with + and _ with /.","Validate the length after decoding matches sha512.Size (64 bytes) to also avoid error from the next guard.","Load credentials from a vetted source (env, sealed secret) rather than hand-editing."],"exampleFix":"// before\nbasicauth.New(basicauth.Config{Users: map[string]string{\"admin\": \"{SHA512}\" + urlSafeDigest}})\n\n// after (regenerate as standard base64 of the raw 32/64-byte digest)\nDigest: \"{\"SHA512}\" + base64.StdEncoding.EncodeToString(sha512.Sum512_256(raw)) // ensure 64-byte digest","handlingStrategy":"validation","validationCode":"func validateSHA512Hash(h string) error {\n    if !strings.HasPrefix(h, \"{SHA512}\") { return nil }\n    b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(h, \"{SHA512}\"))\n    if err != nil { return fmt.Errorf(\"bad SHA512 base64: %w\", err) }\n    if len(b) != sha512.Size { return fmt.Errorf(\"SHA512 digest must be %d bytes, got %d\", sha512.Size, len(b)) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate digests with standard base64 (not URL-safe).","Strip whitespace/newlines from credential values before storing.","Validate every Users entry in unit tests by re-running parseHashedPassword.","Prefer bcrypt ($2b$) for new deployments to avoid the SHA legacy path."],"tags":["basicauth","authentication","password-hash","base64","config"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}