slackhq/nebula · error

recombine cert: %w

Error message

recombine cert: %w

What it means

validateCert wraps errors from cert.Recombine as 'recombine cert: %w'. Recombine merges the peer's certificate bytes with the peer's Noise static key to reconstruct the full certificate and validate it cryptographically. Failure means the cert bytes, peer static key, curve, or network (CA) don't fit together — the presented certificate cannot be recombined for the given curve/version.

Source

Thrown at handshake/machine.go:356

	return nil
}

func (m *Machine) validateCert(payload Payload) error {
	cred := m.getCred(m.myVersion)
	if cred == nil {
		m.failed = true
		return fmt.Errorf("%w: %v", ErrNoCredential, m.myVersion)
	}
	rc, err := cert.Recombine(
		cert.Version(payload.CertVersion),
		payload.Cert,
		m.hs.PeerStatic(),
		cred.Cert.Curve(),
	)
	if err != nil {
		m.failed = true
		return fmt.Errorf("recombine cert: %w", err)
	}

	if !bytes.Equal(rc.PublicKey(), m.hs.PeerStatic()) {
		m.failed = true
		return ErrPublicKeyMismatch
	}

	// Version negotiation, if the peer sent a different version and we have it, switch
	if rc.Version() != m.myVersion {
		if m.getCred(rc.Version()) != nil {
			m.myVersion = rc.Version()
		}
	}

	verified, err := m.verifier(rc)
	if err != nil {
		m.failed = true
		return fmt.Errorf("verify cert: %w", err)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Re-issue the peer's certificate with nebula-cert matching the CA's curve and version
  2. Confirm all hosts use certs signed by the same CA and curve family
  3. Upgrade peers so certificate encoding versions match
  4. Replace the cert payload source — if this is a middlebox/proxy issue, verify end-to-end packet integrity

Example fix

// before: CA on curve25519, node cert issued as P-256
nebula-cert sign -name host -curve P256 ...
// after: match the CA curve
nebula-cert sign -ca ca.crt -key ca.key -name host -ip 10.0.0.2/24 -curve CURVE25519
Defensive patterns

Strategy: validation

Validate before calling

// before deployment, check cert/CA curve compatibility
caCert, _ := cert.UnmarshalNebulaCertificate(caPEM)
hostCert, _ := cert.UnmarshalNebulaCertificate(hostPEM)
if caCert.Curve() != hostCert.Curve() {
	return fmt.Errorf("cert curve %v does not match CA curve %v", hostCert.Curve(), caCert.Curve())
}

Try / catch

_, _, err := machine.ProcessPacket(pkt)
if err != nil && strings.Contains(err.Error(), "recombine cert:") {
	// peer cert unusable for this curve/version — reject and reissue peer cert
}

Prevention

When it happens

Trigger: ProcessPacket -> processPayload -> validateCert where cert.Recombine(cert.Version(payload.CertVersion), payload.Cert, m.hs.PeerStatic(), cred.Cert.Curve(), ...) errors — cert version mismatch with curve, malformed cert bytes in the payload, or peer static key inconsistent with the certificate's signature.

Common situations: Peer certificate issued for a different elliptic curve (P-256 vs curve25519) than the CA, tampered/forged cert payload, cert bytes truncated by an intermediary, incompatible nebula-cert versions between CA and node certs.

Related errors


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