golang/go · error

ecdsa: curve not supported by ParseRawPrivateKey

Error message

ecdsa: curve not supported by ParseRawPrivateKey

What it means

Thrown by ParseRawPrivateKey when the provided curve does not match P224, P256, P384, or P521 in the switch statement. Only standard NIST curves are supported for parsing raw (unencoded) ECDSA private key scalars.

Source

Thrown at src/crypto/ecdsa/ecdsa.go:257

//
// ParseRawPrivateKey accepts the same format as [ecdh.Curve.NewPrivateKey] does
// for NIST curves, but returns a [PrivateKey] instead of an [ecdh.PrivateKey].
//
// Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
// which can be parsed with [crypto/x509.ParseECPrivateKey] or
// [crypto/x509.ParsePKCS8PrivateKey] (and [encoding/pem]).
func ParseRawPrivateKey(curve elliptic.Curve, data []byte) (*PrivateKey, error) {
	switch curve {
	case elliptic.P224():
		return parseRawPrivateKey(ecdsa.P224(), nistec.NewP224Point, curve, data)
	case elliptic.P256():
		return parseRawPrivateKey(ecdsa.P256(), nistec.NewP256Point, curve, data)
	case elliptic.P384():
		return parseRawPrivateKey(ecdsa.P384(), nistec.NewP384Point, curve, data)
	case elliptic.P521():
		return parseRawPrivateKey(ecdsa.P521(), nistec.NewP521Point, curve, data)
	default:
		return nil, errors.New("ecdsa: curve not supported by ParseRawPrivateKey")
	}
}

func parseRawPrivateKey[P ecdsa.Point[P]](c *ecdsa.Curve[P], newPoint func() P, curve elliptic.Curve, data []byte) (*PrivateKey, error) {
	q, err := newPoint().ScalarBaseMult(data)
	if err != nil {
		return nil, err
	}
	k, err := ecdsa.NewPrivateKey(c, data, q.Bytes())
	if err != nil {
		return nil, err
	}
	return privateKeyFromFIPS(curve, k)
}

// Bytes encodes the private key as a fixed-length big-endian integer according
// to SEC 1, Version 2.0, Section 2.3.6 (sometimes referred to as the raw
// format). It returns an error if the private key is invalid.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass the canonical curve singleton (e.g., elliptic.P256()) not curve.Params().
  2. For non-NIST curves, parse the scalar manually and construct the PrivateKey by computing D*G via ScalarBaseMult.
  3. Validate the curve matches one of the four supported singletons before calling ParseRawPrivateKey.

Example fix

// before
priv, err := ecdsa.ParseRawPrivateKey(curve.Params(), scalarBytes)

// after
priv, err := ecdsa.ParseRawPrivateKey(elliptic.P256(), scalarBytes)
Defensive patterns

Strategy: validation

Validate before calling

func isSupportedCurve(c elliptic.Curve) bool {
    switch c {
    case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
        return true
    }
    return false
}
// call before: ParseRawPrivateKey(curve, data)

Try / catch

priv, err := ecdsa.ParseRawPrivateKey(curve, data)
if err != nil {
    return fmt.Errorf("cannot parse private key on curve %s: %w", curve.Params().Name, err)
}

Prevention

When it happens

Trigger: Calling ParseRawPrivateKey with a custom elliptic.Curve, or passing curve.Params() instead of the singleton curve object. The switch compares against the singleton returns of elliptic.P224()/P256()/P384()/P521().

Common situations: Using a third-party curve implementation; mistakenly passing curve.Params() which is a different type than the curve singleton; working with non-NIST curves like SEC curves outside the standard set.

Related errors


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