golang/go · error
ecdsa: curve not supported by PrivateKey.Bytes
Error message
ecdsa: curve not supported by PrivateKey.Bytes
What it means
Thrown by PrivateKey.Bytes() when priv.Curve does not match P224, P256, P384, or P521. Only standard NIST curves have serialization implemented through the internal FIPS ecdsa package. The raw private key scalar serialization is not available for custom or unsupported curves.
Source
Thrown at src/crypto/ecdsa/ecdsa.go:296
// [elliptic.P384], or [elliptic.P521], or Bytes returns an error.
//
// Bytes returns the same format as [ecdh.PrivateKey.Bytes] does for NIST curves.
//
// Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
// which can be generated with [crypto/x509.MarshalECPrivateKey] or
// [crypto/x509.MarshalPKCS8PrivateKey] (and [encoding/pem]).
func (priv *PrivateKey) Bytes() ([]byte, error) {
switch priv.Curve {
case elliptic.P224():
return privateKeyBytes(ecdsa.P224(), priv)
case elliptic.P256():
return privateKeyBytes(ecdsa.P256(), priv)
case elliptic.P384():
return privateKeyBytes(ecdsa.P384(), priv)
case elliptic.P521():
return privateKeyBytes(ecdsa.P521(), priv)
default:
return nil, errors.New("ecdsa: curve not supported by PrivateKey.Bytes")
}
}
func privateKeyBytes[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) ([]byte, error) {
k, err := privateKeyToFIPS(c, priv)
if err != nil {
return nil, err
}
return k.Bytes(), nil
}
// Sign signs a hash (which should be the result of hashing a larger message
// with opts.HashFunc()) 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, like [SignASN1].
//
// If random is not nil, the signature is randomized. Most applications should use
// [crypto/rand.Reader] as random, but unless GODEBUG=cryptocustomrand=1 is set, aView on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the PrivateKey was created with a standard NIST curve singleton before calling Bytes().
- For non-NIST curves, serialize priv.D manually using FillBytes to the curve's byte size.
- Validate priv.Curve at construction or deserialization time, rejecting unsupported curves early.
Example fix
// before
b, err := priv.Bytes()
// after
switch priv.Curve {
case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
b, err = priv.Bytes()
default:
size := (priv.Curve.Params().N.BitLen() + 7) / 8
b = priv.D.FillBytes(make([]byte, size))
} Defensive patterns
Strategy: validation
Validate before calling
func canSerializePrivateKey(priv *ecdsa.PrivateKey) bool {
switch priv.Curve {
case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
return true
}
return false
} Try / catch
b, err := priv.Bytes()
if err != nil {
// manual serialization for non-NIST curves
size := (priv.Curve.Params().N.BitLen() + 7) / 8
b = priv.D.FillBytes(make([]byte, size))
} Prevention
- Use standard NIST curves for all keys that need library serialization support.
- Validate the curve at key construction time to fail early.
When it happens
Trigger: Calling Bytes() on a PrivateKey whose Curve is a non-NIST curve or was set using .Params() instead of the singleton. The switch falls through to the default branch.
Common situations: Manually constructing a PrivateKey struct with a custom curve; loading keys from non-standard formats; using curve.Params() as the Curve field instead of the singleton.
Related errors
- ecdsa: curve not supported by PublicKey.Bytes
- ecdsa: curve not supported by ParseRawPrivateKey
- ecdsa: unsupported curve by crypto/ecdh
- ecdsa: curve not supported by ParseUncompressedPublicKey
- ecdsa: curve not supported by deterministic signatures
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/0de5c47d41bcf590.
Report an issue: GitHub.