{"record":{"id":"d39a3a6277e8adac","repo":"golang/go","slug":"mldsa-invalid-signeropts","errorCode":null,"errorMessage":"mldsa: invalid SignerOpts","messagePattern":"mldsa: invalid SignerOpts","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/mldsa/mldsa_fips140v1.26.go","lineNumber":94,"sourceCode":"\t\treturn false\n\t}\n\treturn sk.k.Equal(&other.k)\n}\n\n// PublicKey returns the corresponding [PublicKey] for this private key.\nfunc (sk *PrivateKey) PublicKey() *PublicKey {\n\t// Making a copy severs the pointer relationship between the private and\n\t// public keys, so that keeping the public key around doesn't keep the\n\t// private key alive. This costs a copy and an allocation.\n\treturn &PublicKey{p: *sk.k.PublicKey()}\n}\n\n// Bytes returns the private key seed.\nfunc (sk *PrivateKey) Bytes() []byte {\n\treturn sk.k.Bytes()\n}\n\nvar errInvalidSignerOpts = errors.New(\"mldsa: invalid SignerOpts\")\n\n// Sign returns a signature of the given message using this private key.\n//\n// If opts is nil or opts.HashFunc returns zero, the message is signed directly.\n// If opts.HashFunc returns [crypto.MLDSAMu], the provided message must be a\n// [pre-hashed μ message representative]. opts can be of type *[Options] if a\n// context string is desired along with a directly-signed message. The io.Reader\n// argument is ignored.\n//\n// [pre-hashed μ message representative]: https://www.rfc-editor.org/rfc/rfc9881.html#externalmu\nfunc (sk *PrivateKey) Sign(_ io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {\n\tif sk.k == (mldsa.PrivateKey{}) {\n\t\treturn nil, errors.New(\"mldsa: zero private key\")\n\t}\n\tif opts == nil {\n\t\topts = &Options{}\n\t}\n\tswitch opts.HashFunc() {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/mldsa/mldsa_fips140v1.26.go#L76-L112","documentation":"Returned by PrivateKey.Sign when the crypto.SignerOpts passed in has a HashFunc() that returns a value other than 0 (direct message signing) or crypto.MLDSAMu (pre-hashed external-μ signing). ML-DSA supports exactly these two signing modes per FIPS 204 / RFC 9881; any other hash identifier is rejected as unsupported. The error is the package-level var errInvalidSignerOpts.","triggerScenarios":"Calling sk.Sign(nil, msg, opts) where opts.HashFunc() returns a conventional hash crypto.Hash (e.g. crypto.SHA256) instead of 0 or crypto.MLDSAMu. Passing a custom SignerOpts whose HashFunc() yields an unrecognized uint value.","commonSituations":"Adapting existing ECDSA/Ed25519 signing code to ML-DSA and reusing a SHA-256 opts struct. Misunderstanding that ML-DSA is not a pre-hash-signature scheme by default and assuming opts.HashFunc must return a real hash. Forgetting to pass nil or &Options{}.","solutions":["Pass nil or a *mldsa.Options with the zero-value hash for direct message signing: sk.Sign(rand, message, nil).","For pre-hashed μ signing, use a SignerOpts whose HashFunc() returns crypto.MLDSAMu and pre-compute the μ representative.","If you need to attach a context string, pass &mldsa.Options{Context: \"ctx\"} with HashFunc left at 0."],"exampleFix":"// before\nopts := &rsa.PSSOptions{Hash: crypto.SHA256}\nsig, err := sk.Sign(rand.Reader, digest, opts) // errInvalidSignerOpts\n\n// after\nsig, err := sk.Sign(rand.Reader, message, nil) // direct signing","handlingStrategy":"type-guard","validationCode":"// Validate SignerOpts before calling Sign.\nfunc validMldsaOpts(opts crypto.SignerOpts) bool {\n    if opts == nil { return true } // treated as direct signing\n    hf := opts.HashFunc()\n    return hf == 0 || hf == crypto.MLDSAMu\n}\nif !validMldsaOpts(opts) { return errInvalidSignerOpts }\nsig, err := sk.Sign(nil, msg, opts)","typeGuard":"func isMldsaApprovedOpts(opts crypto.SignerOpts) bool {\n    if opts == nil { return true }\n    hf := opts.HashFunc()\n    return hf == 0 || hf == crypto.MLDSAMu\n}","tryCatchPattern":"sig, err := sk.Sign(nil, msg, opts)\nif err != nil {\n    if errors.Is(err, mldsaErrInvalidSignerOpts) {\n        // fix opts to nil or MLDSAMu and retry once\n    }\n    return err\n}","preventionTips":["Standardize on nil or &mldsa.Options{} for direct signing across the codebase.","Never reuse RSA/ECDSA SignerOpts structs with ML-DSA.","Add a unit test asserting opts.HashFunc() returns 0 or crypto.MLDSAMu for every signing call site."],"tags":["cryptography","go","post-quantum","mldsa","signer-opts"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}