golang/go · error
crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-
Error message
crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-only mode
What it means
In FIPS 140-only mode, NIST-curve ECDH key generation must use crypto/rand.Reader specifically; any other io.Reader is rejected as a non-approved randomness source. The check runs after wiring the reader through rand.CustomReader, comparing against fips140only.ApprovedRandomReader.
Source
Thrown at src/crypto/ecdh/nist.go:51
return nil, err
}
pub, err := key.PublicKey()
if err != nil {
return nil, err
}
k := &PrivateKey{
curve: c,
privateKey: bytes,
publicKey: &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub},
boring: key,
}
return k, nil
}
r = rand.CustomReader(r)
if fips140only.Enforced() && !fips140only.ApprovedRandomReader(r) {
return nil, errors.New("crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-only mode")
}
privateKey, err := c.generate(r)
if err != nil {
return nil, err
}
k := &PrivateKey{
curve: c,
privateKey: privateKey.Bytes(),
fips: privateKey,
publicKey: &PublicKey{
curve: c,
publicKey: privateKey.PublicKey().Bytes(),
fips: privateKey.PublicKey(),
},
}
if boring.Enabled {View on GitHub (pinned to b6b368adc5)
Solutions
- Pass crypto/rand.Reader (or nil where the API defaults to it) in FIPS builds.
- For tests, use testing/cryptotest.SetGlobalRandom instead of injecting a custom reader.
- Remove custom reader indirection in production FIPS paths.
Example fix
// before priv, err := curve.GenerateKey(myTestReader) // fails in FIPS mode // after priv, err := curve.GenerateKey(rand.Reader)
Defensive patterns
Strategy: validation
Validate before calling
func genECDH(curve ecdh.Curve, r io.Reader) (*ecdh.PrivateKey, error) {
if r == nil || (fipsEnabled() && !isApprovedReader(r)) {
r = cryptoRand.Reader
}
return curve.GenerateKey(r)
} Type guard
func isApprovedReader(r io.Reader) bool { return r == cryptoRand.Reader } Try / catch
priv, err := curve.GenerateKey(r)
if err != nil && strings.Contains(err.Error(), "FIPS 140-only mode") {
priv, err = curve.GenerateKey(cryptoRand.Reader)
} Prevention
- Always pass crypto/rand.Reader for key generation in FIPS builds.
- Use testing/cryptotest.SetGlobalRandom for tests instead of custom readers.
- Avoid abstracting randomness behind custom reader types in production.
When it happens
Trigger: Calling ecdh.P256().GenerateKey(customReader) (or P384/P521) in a FIPS-only binary where customReader is not crypto/rand.Reader, e.g. a deterministic test reader or a custom entropy pool.
Common situations: Passing a seeded test reader in FIPS builds; using a hardware RNG wrapper that is not crypto/rand.Reader; code that abstracted randomness behind an interface.
Related errors
- crypto/ecdh: use of X25519 is not allowed in FIPS 140-only m
- 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/5e7b40204f06ad7c.
Report an issue: GitHub.