{"record":{"id":"c288250dc35beb63","repo":"golang/go","slug":"ed25519-bad-ed25519ctx-context-length-l","errorCode":null,"errorMessage":"ed25519: bad Ed25519ctx context length: {l}","messagePattern":"ed25519: bad Ed25519ctx context length: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/ed25519/ed25519.go","lineNumber":211,"sourceCode":"\t\treturn nil, errors.New(\"ed25519: bad Ed25519ph context length: \" + strconv.Itoa(l))\n\t}\n\treturn signWithDom(signature, priv, message, domPrefixPh, context), nil\n}\n\nfunc SignCtx(priv *PrivateKey, message []byte, context string) ([]byte, error) {\n\t// Outline the function body so that the returned signature can be\n\t// stack-allocated.\n\tsignature := make([]byte, signatureSize)\n\treturn signCtx(signature, priv, message, context)\n}\n\nfunc signCtx(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) {\n\tfipsSelfTest()\n\t// FIPS 186-5 specifies Ed25519 and Ed25519ph (with context), but not Ed25519ctx.\n\tfips140.RecordNonApproved()\n\t// Note that per RFC 8032, Section 5.1, the context SHOULD NOT be empty.\n\tif l := len(context); l > 255 {\n\t\treturn nil, errors.New(\"ed25519: bad Ed25519ctx context length: \" + strconv.Itoa(l))\n\t}\n\treturn signWithDom(signature, priv, message, domPrefixCtx, context), nil\n}\n\nfunc signWithDom(signature []byte, priv *PrivateKey, message []byte, domPrefix, context string) []byte {\n\tmh := sha512.New()\n\tif domPrefix != domPrefixPure {\n\t\tmh.Write([]byte(domPrefix))\n\t\tmh.Write([]byte{byte(len(context))})\n\t\tmh.Write([]byte(context))\n\t}\n\tmh.Write(priv.prefix[:])\n\tmh.Write(message)\n\tmessageDigest := make([]byte, 0, sha512Size)\n\tmessageDigest = mh.Sum(messageDigest)\n\tr, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)\n\tif err != nil {\n\t\tpanic(\"ed25519: internal error: setting scalar failed\")","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/ed25519/ed25519.go#L193-L229","documentation":"Returned by SignCtx (Ed25519ctx) when the context string exceeds 255 bytes. RFC 8032 limits context to 255 bytes for both Ed25519ctx and Ed25519ph. Also note FIPS 186-5 marks Ed25519ctx as non-approved (RecordNonApproved is called).","triggerScenarios":"Calling fips140/ed25519.SignCtx(priv, message, context) with len(context) > 255.","commonSituations":"Same as 347 — oversized domain-separation string. Additionally, choosing SignCtx without realizing FIPS mode treats Ed25519ctx as non-approved.","solutions":["Reduce context to <= 255 bytes; prefer a short identifier.","For FIPS-approved signing with context, use SignPH (Ed25519ph) instead of SignCtx.","Hash long context material down to 32 bytes before passing."],"exampleFix":"// before\nsig, err := ed25519.SignCtx(priv, msg, veryLongCtx)\n\n// after\nctxHash := sha256.Sum256([]byte(veryLongCtx))\nsig, err := ed25519.SignCtx(priv, msg, string(ctxHash[:]))","handlingStrategy":"validation","validationCode":"if len(context) > 255 {\n    h := sha256.Sum256([]byte(context))\n    context = string(h[:])\n}\nsig, err := ed25519.SignCtx(priv, message, context)","typeGuard":null,"tryCatchPattern":"sig, err := ed25519.SignCtx(priv, message, context)\nif err != nil {\n    if strings.Contains(err.Error(), \"bad Ed25519ctx context length\") {\n        return nil, fmt.Errorf(\"context too long (%d > 255)\", len(context))\n    }\n    return nil, err\n}","preventionTips":["Remember Ed25519ctx is non-approved in FIPS mode — prefer Ed25519ph if you need context binding.","Keep context short and stable.","Hash long contexts down to a fixed size."],"tags":["crypto","ed25519","ed25519ctx","fips140","validation","context"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}