golang/go · error
crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140
Error message
crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode
What it means
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.
Source
Thrown at src/crypto/ed25519/ed25519.go:116
k, err := privateKeyCache.Get(&priv[0], func() (*ed25519.PrivateKey, error) {
return ed25519.NewPrivateKey(priv)
}, func(k *ed25519.PrivateKey) bool {
return subtle.ConstantTimeCompare(priv, k.Bytes()) == 1
})
if err != nil {
return nil, err
}
hash := opts.HashFunc()
context := ""
if opts, ok := opts.(*Options); ok {
context = opts.Context
}
switch {
case hash == crypto.SHA512: // Ed25519ph
return ed25519.SignPH(k, message, context)
case hash == crypto.Hash(0) && context != "": // Ed25519ctx
if fips140only.Enforced() {
return nil, errors.New("crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode")
}
return ed25519.SignCtx(k, message, context)
case hash == crypto.Hash(0): // Ed25519
return ed25519.Sign(k, message), nil
default:
return nil, errors.New("ed25519: expected opts.HashFunc() zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)")
}
}
// Options can be used with [PrivateKey.Sign] or [VerifyWithOptions]
// to select Ed25519 variants.
type Options struct {
// Hash can be zero for regular Ed25519, or crypto.SHA512 for Ed25519ph.
Hash crypto.Hash
// Context, if not empty, selects Ed25519ctx or provides the context string
// for Ed25519ph. It can be at most 255 bytes in length.
Context stringView on GitHub (pinned to b6b368adc5)
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.
Example fix
// before
opts := ed25519.Options{Context: "app-v1"}
sig, err := priv.Sign(rand.Reader, msg, &opts) // FIPS-only -> error 248
// after
sig, err := priv.Sign(rand.Reader, msg, crypto.Hash(0)) // plain Ed25519 Defensive patterns
Strategy: validation
Validate before calling
if opts, ok := signOpts.(*ed25519.Options); ok && opts.Context != "" && fips140only.Enforced() {
return errors.New("Ed25519ctx not allowed in FIPS 140-only mode")
} Type guard
func isEd25519ctx(o *ed25519.Options) bool {
return o != nil && o.Hash == crypto.Hash(0) && o.Context != ""
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- crypto/des: use of DES is not allowed in FIPS 140-only mode
- crypto/des: use of TripleDES is not allowed in FIPS 140-only
- crypto/dsa: use of DSA is not allowed in FIPS 140-only mode
- crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-
- crypto/ecdh: use of X25519 is not allowed in FIPS 140-only m
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/d7ad815d164afb0d.
Report an issue: GitHub.