{"record":{"id":"d7ad815d164afb0d","repo":"golang/go","slug":"crypto-ed25519-use-of-ed25519ctx-is-not-allowed-i","errorCode":null,"errorMessage":"crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode","messagePattern":"crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/ed25519/ed25519.go","lineNumber":116,"sourceCode":"\tk, err := privateKeyCache.Get(&priv[0], func() (*ed25519.PrivateKey, error) {\n\t\treturn ed25519.NewPrivateKey(priv)\n\t}, func(k *ed25519.PrivateKey) bool {\n\t\treturn subtle.ConstantTimeCompare(priv, k.Bytes()) == 1\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thash := opts.HashFunc()\n\tcontext := \"\"\n\tif opts, ok := opts.(*Options); ok {\n\t\tcontext = opts.Context\n\t}\n\tswitch {\n\tcase hash == crypto.SHA512: // Ed25519ph\n\t\treturn ed25519.SignPH(k, message, context)\n\tcase hash == crypto.Hash(0) && context != \"\": // Ed25519ctx\n\t\tif fips140only.Enforced() {\n\t\t\treturn nil, errors.New(\"crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode\")\n\t\t}\n\t\treturn ed25519.SignCtx(k, message, context)\n\tcase hash == crypto.Hash(0): // Ed25519\n\t\treturn ed25519.Sign(k, message), nil\n\tdefault:\n\t\treturn nil, errors.New(\"ed25519: expected opts.HashFunc() zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)\")\n\t}\n}\n\n// Options can be used with [PrivateKey.Sign] or [VerifyWithOptions]\n// to select Ed25519 variants.\ntype Options struct {\n\t// Hash can be zero for regular Ed25519, or crypto.SHA512 for Ed25519ph.\n\tHash crypto.Hash\n\n\t// Context, if not empty, selects Ed25519ctx or provides the context string\n\t// for Ed25519ph. It can be at most 255 bytes in length.\n\tContext string","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/ed25519/ed25519.go#L98-L134","documentation":"Thrown in ed25519.go:116 during PrivateKey.Sign when Ed25519ctx is selected (Hash==0 && Context != \"\") and fips140only.Enforced() is true. Ed25519ctx (pre-hash context variant) is not an approved FIPS 140 algorithm, so it is blocked in FIPS 140-only mode.","triggerScenarios":"Calling priv.Sign with ed25519.Options{Context: \"myctx\"} (non-empty Context, default Hash) while FIPS 140-only is active. This routes to the Ed25519ctx branch and hits the guard.","commonSituations":"FIPS-validated build using context-separated Ed25519 (common in some protocols/age-style tools); a library defaulting to a context string; enabling GOFIPS/fips140 build tag.","solutions":["Drop the Context for plain Ed25519 (Options{Hash: crypto.Hash(0), Context: \"\"}), or use Ed25519ph (Hash: crypto.SHA512) which is FIPS-approved.","Disable FIPS 140-only mode if Ed25519ctx is a protocol requirement and FIPS compliance is not.","Review the signer's Options to confirm Context is empty under FIPS builds."],"exampleFix":"// before\nopts := ed25519.Options{Context: \"app-v1\"}\nsig, err := priv.Sign(rand.Reader, msg, &opts) // FIPS-only -> error 248\n\n// after\nsig, err := priv.Sign(rand.Reader, msg, crypto.Hash(0)) // plain Ed25519","handlingStrategy":"validation","validationCode":"if opts, ok := signOpts.(*ed25519.Options); ok && opts.Context != \"\" && fips140only.Enforced() {\n    return errors.New(\"Ed25519ctx not allowed in FIPS 140-only mode\")\n}","typeGuard":"func isEd25519ctx(o *ed25519.Options) bool {\n    return o != nil && o.Hash == crypto.Hash(0) && o.Context != \"\"\n}","tryCatchPattern":null,"preventionTips":["Keep Options.Context empty under FIPS builds, or use Ed25519ph (Hash: SHA512).","Branch on key type in generic sign helpers to set Ed25519 Options correctly.","Document which Ed25519 variants are FIPS-approved for your callers."],"tags":["go","crypto","ed25519","fips","compliance"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}