{"record":{"id":"549ccee3747850bf","repo":"golang/go","slug":"crypto-rsa-invalid-pss-salt-length-549cce","errorCode":null,"errorMessage":"crypto/rsa: invalid PSS salt length","messagePattern":"crypto/rsa: invalid PSS salt length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/rsa/fips.go","lineNumber":121,"sourceCode":"\t}\n\n\tsaltLength := opts.saltLength()\n\tif fips140only.Enforced() && saltLength > h.Size() {\n\t\treturn nil, errors.New(\"crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode\")\n\t}\n\tswitch saltLength {\n\tcase PSSSaltLengthAuto:\n\t\tsaltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h)\n\t\tif err != nil {\n\t\t\treturn nil, fipsError(err)\n\t\t}\n\tcase PSSSaltLengthEqualsHash:\n\t\tsaltLength = h.Size()\n\tdefault:\n\t\t// If we get here saltLength is either > 0 or < -1, in the\n\t\t// latter case we fail out.\n\t\tif saltLength <= 0 {\n\t\t\treturn nil, errors.New(\"crypto/rsa: invalid PSS salt length\")\n\t\t}\n\t}\n\n\treturn fipsError2(rsa.SignPSS(random, k, h, digest, saltLength))\n}\n\n// VerifyPSS verifies a PSS signature.\n//\n// A valid signature is indicated by returning a nil error. digest must be the\n// result of hashing the input message using the given hash function. The opts\n// argument may be nil, in which case sensible defaults are used. opts.Hash is\n// ignored.\n//\n// The inputs are not considered confidential, and may leak through timing side\n// channels, or if an attacker has control of part of the inputs.\nfunc VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {\n\tif err := checkPublicKeySize(pub); err != nil {\n\t\treturn err","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/rsa/fips.go#L103-L139","documentation":"Thrown by SignPSS when opts.SaltLength resolves to a value <= 0 that is neither PSSSaltLengthAuto (0) nor PSSSaltLengthEqualsHash (-1) — i.e. a negative number below -1, or it slipped past those two cases. The switch handles the two sentinels; the default branch rejects any remaining non-positive length. This is a general input validation, NOT FIPS-specific (it fires regardless of enforcement).","triggerScenarios":"Passing &rsa.PSSOptions{SaltLength: -2} (or any value < -1) to SignPSS. A zero-value PSSOptions does NOT trip this because SaltLength 0 == PSSSaltLengthAuto which is handled. An uninitialized *int from a config struct that defaults to a negative sentinel accidentally can trip it.","commonSituations":"Config file maps a missing salt-length field to -1 as 'not set' but -1 is actually PSSSaltLengthEqualsHash; a separate 'disabled' code path uses -2 and hits validation. Off-by-one arithmetic on salt length producing a negative result.","solutions":["Use rsa.PSSSaltLengthEqualsHash (-1) or rsa.PSSSaltLengthAuto (0) instead of custom negative values.","If you need an explicit length, ensure it is a positive integer greater than zero.","Validate opts.SaltLength before calling SignPSS if the value comes from untrusted/config input."],"exampleFix":"// before\nopts := &rsa.PSSOptions{SaltLength: configSalt /* accidentally -2 */}\nsig, err := rsa.SignPSS(rand.Reader, priv, crypto.SHA256, digest, opts)\n\n// after\nif opts.SaltLength < -1 || (opts.SaltLength < 0 && opts.SaltLength != rsa.PSSSaltLengthEqualsHash) {\n    opts.SaltLength = rsa.PSSSaltLengthEqualsHash\n}\nsig, err := rsa.SignPSS(rand.Reader, priv, crypto.SHA256, digest, opts)","handlingStrategy":"validation","validationCode":"func validatePSSSaltLength(opts *rsa.PSSOptions) error {\n    if opts == nil {\n        return nil\n    }\n    sl := opts.SaltLength\n    if sl == rsa.PSSSaltLengthAuto || sl == rsa.PSSSaltLengthEqualsHash {\n        return nil\n    }\n    if sl <= 0 {\n        return fmt.Errorf(\"invalid PSS salt length %d: use PSSSaltLengthAuto, PSSSaltLengthEqualsHash, or a positive int\", sl)\n    }\n    return nil\n}\nif err := validatePSSSaltLength(opts); err != nil { return err }","typeGuard":"func isValidSaltLength(sl int) bool {\n    return sl == rsa.PSSSaltLengthAuto ||\n        sl == rsa.PSSSaltLengthEqualsHash ||\n        sl > 0\n}","tryCatchPattern":null,"preventionTips":["Never use arbitrary negative sentinels for PSS salt length — only 0 and -1 are defined.","When loading salt length from config, coerce unknown/missing values to PSSSaltLengthEqualsHash rather than passing them through.","Unit-test the PSS options construction with a table of salt-length values."],"tags":["crypto","rsa","pss","validation","signing"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}