golang/go · error
crypto/ecdh: use of X25519 is not allowed in FIPS 140-only m
Error message
crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode
What it means
In FIPS 140-only mode, X25519 key generation is refused because X25519 is not in the FIPS-approved algorithm set (it is a CFRG curve, not a NIST/FIPS curve). The check is the first statement in x25519Curve.GenerateKey.
Source
Thrown at src/crypto/ecdh/x25519.go:39
// X25519 returns a [Curve] which implements the X25519 function over Curve25519
// (RFC 7748, Section 5).
//
// Multiple invocations of this function will return the same value, so it can
// be used for equality checks and switch statements.
func X25519() Curve { return x25519 }
var x25519 = &x25519Curve{}
type x25519Curve struct{}
func (c *x25519Curve) String() string {
return "X25519"
}
func (c *x25519Curve) GenerateKey(r io.Reader) (*PrivateKey, error) {
if fips140only.Enforced() {
return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode")
}
r = rand.CustomReader(r)
key := make([]byte, x25519PrivateKeySize)
if _, err := io.ReadFull(r, key); err != nil {
return nil, err
}
return c.NewPrivateKey(key)
}
func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) {
if fips140only.Enforced() {
return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode")
}
if len(key) != x25519PrivateKeySize {
return nil, errors.New("crypto/ecdh: invalid private key size")
}
publicKey := make([]byte, x25519PublicKeySize)
x25519Basepoint := [32]byte{9}View on GitHub (pinned to b6b368adc5)
Solutions
- Use a FIPS-approved NIST curve instead: ecdh.P256().GenerateKey(rand.Reader).
- If FIPS-only is not required, rebuild without FIPS 140-only enforcement.
- Isolate X25519 usage in a non-FIPS-only component if interop demands it (still non-compliant for the FIPS boundary).
Example fix
// before priv, err := ecdh.X25519().GenerateKey(rand.Reader) // after priv, err := ecdh.P256().GenerateKey(rand.Reader)
Defensive patterns
Strategy: fallback
Validate before calling
func genKey(curve ecdh.Curve, rand io.Reader) (*ecdh.PrivateKey, error) {
if fipsEnabled() {
curve = ecdh.P256() // X25519 not approved under FIPS
}
return curve.GenerateKey(rand)
} Try / catch
priv, err := ecdh.X25519().GenerateKey(rand.Reader)
if err != nil && strings.Contains(err.Error(), "FIPS 140-only mode") {
priv, err = ecdh.P256().GenerateKey(rand.Reader)
} Prevention
- Do not invoke X25519 in FIPS-only builds; use a NIST curve.
- Negotiate the curve in the protocol so peers align on an approved curve.
- Document curve availability per deployment mode.
When it happens
Trigger: Calling ecdh.X25519().GenerateKey(rand.Reader) in a binary with FIPS 140-only enforcement enabled.
Common situations: Noise/Signal-style protocols or modern key-exchange code paths triggered inside a FIPS-regulated service; FIPS toolchain introduced by CI or deployment policy.
Related errors
- crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-
- 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: private key and public key curves do not match
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/867cf84aeb348de7.
Report an issue: GitHub.