{"record":{"id":"102ece5298496793","repo":"golang/go","slug":"crypto-rsa-salt-length-cannot-be-negative","errorCode":null,"errorMessage":"crypto/rsa: salt length cannot be negative","messagePattern":"crypto/rsa: salt length cannot be negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/rsa/pkcs1v22.go","lineNumber":281,"sourceCode":"\t\treturn hash.Size(), nil\n\t}\n\treturn saltLength, nil\n}\n\n// SignPSS calculates the signature of hashed using RSASSA-PSS.\nfunc SignPSS(rand io.Reader, priv *PrivateKey, hash hash.Hash, hashed []byte, saltLength int) ([]byte, error) {\n\tfipsSelfTest()\n\tfips140.RecordApproved()\n\tcheckApprovedHash(hash)\n\n\t// Note that while we don't commit to deterministic execution with respect\n\t// to the rand stream, we also never applied MaybeReadByte, so per Hyrum's\n\t// Law it's probably relied upon by some. It's a tolerable promise because a\n\t// well-specified number of random bytes is included in the signature, in a\n\t// well-specified way.\n\n\tif saltLength < 0 {\n\t\treturn nil, errors.New(\"crypto/rsa: salt length cannot be negative\")\n\t}\n\t// FIPS 186-5, Section 5.4(g): \"the length (in bytes) of the salt (sLen)\n\t// shall satisfy 0 ≤ sLen ≤ hLen\".\n\tif saltLength > hash.Size() {\n\t\tfips140.RecordNonApproved()\n\t}\n\tsalt := make([]byte, saltLength)\n\tif err := drbg.ReadWithReader(rand, salt); err != nil {\n\t\treturn nil, err\n\t}\n\n\temBits := priv.pub.N.BitLen() - 1\n\tem, err := emsaPSSEncode(hashed, emBits, salt, hash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// RFC 8017: \"Note that the octet length of EM will be one less than k if","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/rsa/pkcs1v22.go#L263-L299","documentation":"rsa.SignPSS requires saltLength >= 0. A negative salt length is meaningless — it would imply a negative-length salt allocation. FIPS 186-5 further requires 0 <= sLen <= hLen; values exceeding hLen are recorded as non-approved but still processed. Only strictly negative values trigger this hard error.","triggerScenarios":"Calling SignPSS with a negative saltLength argument.","commonSituations":"Using rsa.PSSSaltLengthEqualsHash (-1) or rsa.PSSSaltLengthAuto (-2) constants with the internal SignPSS instead of the public API that interprets them; computing saltLength from a subtraction that underflows; an uninitialized int field defaulting to a sentinel negative value.","solutions":["Use a non-negative saltLength: 0 for no salt, hash.Size() for hash-length salt, or a specific byte count","If you intended PSSSaltLengthEqualsHash or PSSSaltLengthAuto, use the higher-level crypto/rsa.SignPSS which interprets those constants","Validate saltLength >= 0 before calling the function"],"exampleFix":"// before\nsig, err := fipsrsa.SignPSS(rand, key, hash, digest, -1) // negative\n\n// after\nsig, err := fipsrsa.SignPSS(rand, key, hash, digest, hash.Size()) // explicit hash-length salt","handlingStrategy":"validation","validationCode":"func validatePSSSaltLength(saltLen int) error {\n    if saltLen < 0 {\n        return fmt.Errorf(\"PSS salt length cannot be negative: %d\", saltLen)\n    }\n    return nil\n}\n\nif err := validatePSSSaltLength(saltLen); err != nil { return err }\nsig, err := rsa.SignPSS(rand, key, hash, digest, &rsa.PSSOptions{SaltLength: saltLen})","typeGuard":null,"tryCatchPattern":"sig, err := rsa.SignPSS(rand, key, hash, digest, opts)\nif err != nil {\n    return fmt.Errorf(\"PSS signing failed: %w\", err)\n}","preventionTips":["Use explicit non-negative salt lengths: 0, hash.Size(), or a specific byte count","Do not pass PSSSaltLengthEqualsHash (-1) or PSSSaltLengthAuto (-2) to the internal FIPS SignPSS","Validate saltLength at the boundary where it enters from configuration"],"tags":["crypto","fips140","rsa","pss","salt-length","input-validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}