golang/go · error

ecdsa: invalid public key encoding

Error message

ecdsa: invalid public key encoding

What it means

Thrown by fips140/ecdsa.NewPublicKey when len(Q) < 1 or Q[0] == 0. An empty point or one beginning with 0x00 (the point-at-infinity / malformed) is rejected up front; SetBytes afterward validates on-curve membership and coordinate ranges per SP 800-89 §5.3.2.

Source

Thrown at src/crypto/internal/fips140/ecdsa/ecdsa.go:190

	d, err := bigmod.NewNat().SetBytes(D, c.N)
	if err != nil {
		return nil, err
	}
	if d.IsZero() == 1 {
		return nil, errors.New("ecdsa: private key is zero")
	}
	priv := &PrivateKey{pub: *pub, d: d.Bytes(c.N)}
	return priv, nil
}

// NewPublicKey creates a new ECDSA public key from the given Q byte slice.
// Q must be the compressed or uncompressed encoding of the public point.
func NewPublicKey[P Point[P]](c *Curve[P], Q []byte) (*PublicKey, error) {
	// SetBytes checks that Q is a valid point on the curve, and that its
	// coordinates are reduced modulo p, fulfilling the requirements of SP
	// 800-89, Section 5.3.2.
	if len(Q) < 1 || Q[0] == 0 {
		return nil, errors.New("ecdsa: invalid public key encoding")
	}
	_, err := c.newPoint().SetBytes(Q)
	if err != nil {
		return nil, err
	}
	return &PublicKey{curve: c.curve, q: Q}, nil
}

// GenerateKey generates a new ECDSA private key pair for the specified curve.
func GenerateKey[P Point[P]](c *Curve[P], rand io.Reader) (*PrivateKey, error) {
	fips140.RecordApproved()

	k, Q, err := randomPoint(c, func(b []byte) error {
		return drbg.ReadWithReader(rand, b)
	})
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Validate len(Q) >= 1 and Q[0] != 0 before calling NewPublicKey.
  2. Re-serialize the point in SEC1 compressed (0x02/0x03) or uncompressed (0x04) form.
  3. Check the upstream parser that produced Q for truncation.

Example fix

// before
pub, err := ecdsa.NewPublicKey(curve, q) // q empty or q[0]==0x00

// after: guard the encoding
if len(q) == 0 || q[0] == 0 {
    return errors.New("invalid public key encoding")
}
pub, err := ecdsa.NewPublicKey(curve, q)
Defensive patterns

Strategy: validation

Validate before calling

if len(Q) < 1 || Q[0] == 0 {
    return errors.New("ecdsa public key encoding is empty or starts with 0x00")
}
return ecdsa.NewPublicKey(curve, Q)

Type guard

func validPubEnc(Q []byte) bool {
    return len(Q) >= 1 && Q[0] != 0
}

Prevention

When it happens

Trigger: Constructing an ECDSA public key from an empty slice, a 0x00-prefixed buffer, or any encoding whose first byte is zero.

Common situations: Parsing a corrupted/truncated certificate or JWK, an uninitialized buffer, or a mis-serialized point that lost its format prefix.

Related errors


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