golang/go · error

crypto/ecdsa: use of custom curves is not allowed in FIPS 14

Error message

crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode

What it means

Thrown by generateLegacy (ecdsa_legacy.go:24) when fips140only.Enforced() is true and a non-NIST (custom/deprecated) elliptic curve is used to generate a key. In FIPS 140-only mode (GOEXPERIMENT=fips140 / GOFIPS=140 behavior), only approved NIST curves (P-224/256/384/521) are permitted; custom curves like secp256k1 or legacy P-521 handling are blocked.

Source

Thrown at src/crypto/ecdsa/ecdsa_legacy.go:24

import (
	"crypto/elliptic"
	"crypto/internal/fips140only"
	"errors"
	"io"
	"math/big"
	"math/rand/v2"

	"golang.org/x/crypto/cryptobyte"
	"golang.org/x/crypto/cryptobyte/asn1"
)

// This file contains a math/big implementation of ECDSA that is only used for
// deprecated custom curves.

func generateLegacy(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
	if fips140only.Enforced() {
		return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode")
	}

	k, err := randFieldElement(c, rand)
	if err != nil {
		return nil, err
	}

	priv := new(PrivateKey)
	priv.PublicKey.Curve = c
	priv.D = k
	priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
	return priv, nil
}

// hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,
// we use the left-most bits of the hash to match the bit-length of the order of
// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Switch to a NIST curve: elliptic.P256(), P384(), or P521().
  2. If a custom curve is mandatory, disable FIPS 140-only mode (remove GOEXPERIMENT=fips140 / the fips140 build tag) and accept the loss of FIPS compliance.
  3. Audit config / key generation code to confirm the curve is NIST-standard under FIPS builds.

Example fix

// before
priv, err := ecdsa.GenerateKey(customCurve, rand.Reader) // FIPS-only -> error 244

// after
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Defensive patterns

Strategy: validation

Validate before calling

if fips140only.Enforced() && !isNISTCurve(curve) {
    return errors.New("custom curves not allowed in FIPS 140-only mode")
}
func isNISTCurve(c elliptic.Curve) bool {
    switch c {
    case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Calling ecdsa.GenerateKey with a custom curve (elliptic curve other than the NIST curves) while FIPS 140-only mode is active. Triggered via the legacy generation path used for non-FIPS curves.

Common situations: Building for a FIPS-validated deployment (GOEXPERIMENT=fips140) and using a non-NIST curve such as secp256k1 (blockchain), or pinning a curve via an old config. Environment: GOFIPS=1 or a fips140 build tag flips enforcement.

Related errors


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