golang/go · error
ed25519: bad Ed25519ctx context length: {l}
Error message
ed25519: bad Ed25519ctx context length: {l} What it means
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).
Source
Thrown at src/crypto/internal/fips140/ed25519/ed25519.go:211
return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l))
}
return signWithDom(signature, priv, message, domPrefixPh, context), nil
}
func SignCtx(priv *PrivateKey, message []byte, context string) ([]byte, error) {
// Outline the function body so that the returned signature can be
// stack-allocated.
signature := make([]byte, signatureSize)
return signCtx(signature, priv, message, context)
}
func signCtx(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) {
fipsSelfTest()
// FIPS 186-5 specifies Ed25519 and Ed25519ph (with context), but not Ed25519ctx.
fips140.RecordNonApproved()
// Note that per RFC 8032, Section 5.1, the context SHOULD NOT be empty.
if l := len(context); l > 255 {
return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l))
}
return signWithDom(signature, priv, message, domPrefixCtx, context), nil
}
func signWithDom(signature []byte, priv *PrivateKey, message []byte, domPrefix, context string) []byte {
mh := sha512.New()
if domPrefix != domPrefixPure {
mh.Write([]byte(domPrefix))
mh.Write([]byte{byte(len(context))})
mh.Write([]byte(context))
}
mh.Write(priv.prefix[:])
mh.Write(message)
messageDigest := make([]byte, 0, sha512Size)
messageDigest = mh.Sum(messageDigest)
r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
if err != nil {
panic("ed25519: internal error: setting scalar failed")View on GitHub (pinned to b6b368adc5)
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.
Example fix
// before sig, err := ed25519.SignCtx(priv, msg, veryLongCtx) // after ctxHash := sha256.Sum256([]byte(veryLongCtx)) sig, err := ed25519.SignCtx(priv, msg, string(ctxHash[:]))
Defensive patterns
Strategy: validation
Validate before calling
if len(context) > 255 {
h := sha256.Sum256([]byte(context))
context = string(h[:])
}
sig, err := ed25519.SignCtx(priv, message, context) Try / catch
sig, err := ed25519.SignCtx(priv, message, context)
if err != nil {
if strings.Contains(err.Error(), "bad Ed25519ctx context length") {
return nil, fmt.Errorf("context too long (%d > 255)", len(context))
}
return nil, err
} Prevention
- 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.
When it happens
Trigger: Calling fips140/ed25519.SignCtx(priv, message, context) with len(context) > 255.
Common situations: Same as 347 — oversized domain-separation string. Additionally, choosing SignCtx without realizing FIPS mode treats Ed25519ctx as non-approved.
Related errors
- ed25519: bad Ed25519ph context length: {l}
- ed25519: bad seed length: {l}
- ed25519: bad private key length: {l}
- ed25519: bad public key length: {l}
- ed25519: bad Ed25519ph message hash length: {l}
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/c288250dc35beb63.
Report an issue: GitHub.