slackhq/nebula · error

curve in cert and private key supplied don't match

Error message

curve in cert and private key supplied don't match

What it means

certificateV1.VerifyPrivateKey first checks that the curve argument matches the curve recorded in the certificate details. This error means the caller supplied a curve that differs from the certificate's own curve, so the private key cannot be meaningfully validated against the cert.

Source

Thrown at cert/cert_v1.go:137

	case Curve_P256:
		pubKey, err := ecdsa.ParseUncompressedPublicKey(elliptic.P256(), key)
		if err != nil {
			return false
		}
		hashed := sha256.Sum256(b)
		return ecdsa.VerifyASN1(pubKey, hashed[:], c.signature)
	default:
		return false
	}
}

func (c *certificateV1) Expired(t time.Time) bool {
	return c.details.notBefore.After(t) || c.details.notAfter.Before(t)
}

func (c *certificateV1) VerifyPrivateKey(curve Curve, key []byte) error {
	if curve != c.details.curve {
		return fmt.Errorf("curve in cert and private key supplied don't match")
	}
	if c.details.isCA {
		switch curve {
		case Curve_CURVE25519:
			// the call to PublicKey below will panic slice bounds out of range otherwise
			if len(key) != ed25519.PrivateKeySize {
				return fmt.Errorf("key was not 64 bytes, is invalid ed25519 private key")
			}

			if !ed25519.PublicKey(c.details.publicKey).Equal(ed25519.PrivateKey(key).Public()) {
				return fmt.Errorf("public key in cert and private key supplied don't match")
			}
		case Curve_P256:
			privkey, err := ecdh.P256().NewPrivateKey(key)
			if err != nil {
				return fmt.Errorf("cannot parse private key as P256: %w", err)
			}
			pub := privkey.PublicKey().Bytes()

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Pass the same curve the certificate was issued with
  2. Regenerate the keypair and certificate on the intended curve so they match
  3. Log/compare curve values to confirm which side is wrong before calling VerifyPrivateKey

Example fix

// before
err := cert.VerifyPrivateKey(cert.Curve_CURVE25519, myKey) // cert is P256
// after
err := cert.VerifyPrivateKey(cert.Curve(), myKey) // derive from the cert itself
Defensive patterns

Strategy: validation

Validate before calling

if curve != cert.Curve() {
    return fmt.Errorf("supplied curve %s does not match cert curve %s", curve, cert.Curve())
}
err := cert.VerifyPrivateKey(curve, key)

Prevention

When it happens

Trigger: Calling cert.VerifyPrivateKey(curve, key) on a certificateV1 where curve != c.details.curve — e.g. passing Curve_CURVE25519 for a P256 cert or vice versa.

Common situations: Hardcoded curve constant that doesn't match the CA/cert generation settings; migration from Curve25519 to P256 (or the reverse) where certs and keys were regenerated inconsistently; copying example code with the wrong Curve enum.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/4c28837caacd5475. Report an issue: GitHub.