{"id":"c89bd9082f552550","repo":"gofiber/fiber","slug":"decode-sha256-password-invalid-length","errorCode":null,"errorMessage":"decode SHA256 password: invalid length","messagePattern":"decode SHA256 password: invalid length","errorType":"validation","errorClass":"ErrInvalidSHA256PasswordLength","httpStatus":null,"severity":"critical","filePath":"middleware/basicauth/config.go","lineNumber":21,"sourceCode":"import (\n\t\"crypto/sha256\"\n\t\"crypto/sha512\"\n\t\"crypto/subtle\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/utils/v2\"\n\t\"golang.org/x/crypto/bcrypt\"\n)\n\nvar (\n\tErrInvalidSHA256PasswordLength = errors.New(\"decode SHA256 password: invalid length\")\n\tErrInvalidSHA512PasswordLength = errors.New(\"decode SHA512 password: invalid length\")\n)\n\n// fallbackDummySHA512 is SHA-512(\"fiber-basicauth-dummy\"), used as a\n// constant-time comparison target when no users are configured.\nvar fallbackDummySHA512 = [sha512.Size]byte{\n\t0x85, 0xc7, 0xd4, 0xbc, 0xec, 0x5f, 0xdf, 0xef, 0xe0, 0x4d, 0xd4, 0x3e, 0xd3, 0xac, 0x45, 0x7c,\n\t0x5e, 0x48, 0x60, 0x74, 0x12, 0x8e, 0xf8, 0xc0, 0xde, 0x39, 0x89, 0xf9, 0x84, 0x0c, 0x50, 0x24,\n\t0x1e, 0xa6, 0x1f, 0x2a, 0x11, 0x97, 0xb1, 0xb9, 0x67, 0xa9, 0xf7, 0x3b, 0x82, 0x8f, 0x95, 0xf5,\n\t0x58, 0xed, 0x3c, 0xab, 0x43, 0x22, 0xf6, 0xfa, 0x84, 0x1d, 0xbc, 0xeb, 0x87, 0xc4, 0x1c, 0x5a,\n}\n\ntype passwordVerifier func(string) bool\n\ntype userVerifiers map[string]passwordVerifier\n\n// Verifier strengths are ordered by expected verification work:\n// bcrypt is strongest because it is adaptive and cost-based, SHA-512 follows","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/basicauth/config.go#L3-L39","documentation":"Returned by basicauth.parseHashedPassword when a user's stored password hash prefixed with {SHA256} (or an unprefixed value treated as raw SHA-256) decodes from base64/hex to a byte slice whose length is not exactly 32 (sha256.Size). A wrong-length digest can never match a real SHA-256 sum, so accepting it would silently reject every login for that user; the middleware surfaces the misconfiguration at startup instead. It is wrapped via buildVerifiers and panics from configDefault when the Config.Users map contains an invalid entry.","triggerScenarios":"Configuring basicauth.Config.Users with a password value like \"{SHA256}<short-base64>\" or a bare hex/base64 string that does not decode to exactly 32 bytes. The error triggers during New() because buildVerifiers → parseHashedPassword runs eagerly at middleware construction (config.go:152-156), so it manifests as a startup panic before the server serves traffic.","commonSituations":"Copy-pasting a truncated hash; storing the hex digest (64 chars) but the library expects raw 32-byte base64; confusing SHA-256 output length with bcrypt; generating the hash with a tool that emits a digest string instead of raw bytes. Migration from another auth library that used a different SHA-256 encoding format.","solutions":["Regenerate the hash as raw 32 bytes and base64-encode it: echo -n 'pass' | openssl dgst -sha256 -binary | base64, then prefix with '{SHA256}'.","Verify the decoded length is 32 bytes: base64-decode your value and check len == 32.","If you have a hex-encoded digest, convert it to the raw-byte base64 form the library expects, or use the '{SHA256}' prefix with raw bytes.","Consider switching to bcrypt ('$2...') hashes which are stronger and have no fixed-length pitfalls."],"exampleFix":"// before\napp.Use(basicauth.New(basicauth.Config{\n  Users: map[string]string{\"admin\": \"{SHA256}\" + hexDigest}, // hexDigest is 64 hex chars\n}))\n// after — convert hex to raw bytes then base64\nraw, _ := hex.DecodeString(hexDigest) // 32 bytes\napp.Use(basicauth.New(basicauth.Config{\n  Users: map[string]string{\"admin\": \"{SHA256}\" + base64.StdEncoding.EncodeToString(raw)},\n}))","handlingStrategy":"validation","validationCode":"// Validate all user hashes before constructing the middleware\nfor user, hash := range users {\n    if strings.HasPrefix(hash, \"{SHA256}\") {\n        b, err := base64.StdEncoding.DecodeString(hash[len(\"{SHA256}\"):])\n        if err != nil || len(b) != sha256.Size {\n            log.Fatalf(\"user %q has invalid SHA256 hash (decoded len=%d)\", user, len(b))\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate hashes with a script that outputs raw-byte base64 and verify len==32.","Prefer bcrypt hashes which avoid fixed-length pitfalls.","Add a startup smoke test that constructs the basicauth middleware with your Users map to catch misconfiguration before deploy."],"tags":["basicauth","authentication","configuration","crypto","startup"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}