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

  1. Pass nil or crypto/rand.Reader as the random source when FIPS mode is active — the library always uses a secure source internally regardless.
  2. 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.
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/596045adf3f8eb71. Report an issue: GitHub.