golang/go · error
crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140
Error message
crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode
What it means
Thrown by generateFIPS during key generation when FIPS 140-only mode is enforced (GOEXPERIMENT or system FIPS policy) and the provided random reader is not crypto/rand.Reader. FIPS 140 requires that all randomness for key generation come from an approved CSPRNG, which in Go is exclusively crypto/rand.Reader.
Source
Thrown at src/crypto/ecdsa/ecdsa.go:373
r = rand.CustomReader(r)
switch c.Params() {
case elliptic.P224().Params():
return generateFIPS(c, ecdsa.P224(), r)
case elliptic.P256().Params():
return generateFIPS(c, ecdsa.P256(), r)
case elliptic.P384().Params():
return generateFIPS(c, ecdsa.P384(), r)
case elliptic.P521().Params():
return generateFIPS(c, ecdsa.P521(), r)
default:
return generateLegacy(c, r)
}
}
func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) {
if fips140only.Enforced() && !fips140only.ApprovedRandomReader(rand) {
return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
}
privateKey, err := ecdsa.GenerateKey(c, rand)
if err != nil {
return nil, err
}
return privateKeyFromFIPS(curve, privateKey)
}
// SignASN1 signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
// returns the ASN.1 encoded signature.
//
// The signature is randomized. Since Go 1.26, a secure source of random bytes
// is always used, and the Reader is ignored unless GODEBUG=cryptocustomrand=1
// is set. This setting will be removed in a future Go release. Instead, use
// [testing/cryptotest.SetGlobalRandom].
func SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {View on GitHub (pinned to b6b368adc5)
Solutions
- Pass nil or crypto/rand.Reader as the random source when FIPS mode is active — the library always uses a secure source internally regardless.
- Since Go 1.26, the Reader parameter is ignored unless GODEBUG=cryptocustomrand=1 is set, so simply pass crypto/rand.Reader and the FIPS check passes.
- For testing, use testing/cryptotest.SetGlobalRandom instead of a custom reader to avoid FIPS violations.
Example fix
// before priv, err := ecdsa.GenerateKey(curve, customReader) // fails in FIPS mode // after priv, err := ecdsa.GenerateKey(curve, rand.Reader) // or nil, both pass FIPS check
Defensive patterns
Strategy: validation
Validate before calling
func isFIPSEnforced() bool {
return fips140only.Enforced() // or check GOEXPERIMENT/system FIPS flag
}
// before GenerateKey: use crypto/rand.Reader if FIPS is active Try / catch
priv, err := ecdsa.GenerateKey(curve, r)
if err != nil && strings.Contains(err.Error(), "FIPS") {
// retry with rand.Reader, or notify user of FIPS requirement
priv, err = ecdsa.GenerateKey(curve, cryptoRand.Reader)
} Prevention
- Always pass crypto/rand.Reader (or nil) to GenerateKey — custom readers are ignored since Go 1.26 anyway.
- Use testing/cryptotest.SetGlobalRandom for test randomness injection in FIPS environments.
When it happens
Trigger: Calling ecdsa.GenerateKey with a custom io.Reader for randomness while the process is running in FIPS 140-only mode (fips140only.Enforced() == true). The fips140only.ApprovedRandomReader check rejects any reader that isn't crypto/rand.Reader.
Common situations: Deploying in a FIPS-compliant environment (e.g., US government or regulated industries) with code that passes a custom or mock random reader; testing code that injects deterministic randomness; upgrading a system to FIPS mode where existing code used non-standard readers.
Related errors
- crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-
- crypto/ecdsa: use of hash functions other than SHA-2 or SHA-
- crypto/ecdsa: use of custom curves is not allowed in FIPS 14
- crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-o
- crypto/cipher: use of GCM with arbitrary IVs is not allowed
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/596045adf3f8eb71.
Report an issue: GitHub.