slackhq/nebula · critical

ErrSignatureMismatch

ErrSignatureMismatch

Error message

certificate signature did not match

What it means

ErrSignatureMismatch is returned by verify (and asserted in cmd/nebula-cert verify tests) when the candidate certificate's signature cannot be verified against the selected CA signer's public key — the certificate was not genuinely signed by that CA or its bytes were altered.

Source

Thrown at cert/errors.go:16

package cert

import (
	"errors"
	"fmt"
)

var (
	ErrBadFormat                  = errors.New("bad wire format")
	ErrRootExpired                = errors.New("root certificate is expired")
	ErrExpired                    = errors.New("certificate is expired")
	ErrNotCA                      = errors.New("certificate is not a CA")
	ErrNotSelfSigned              = errors.New("certificate is not self-signed")
	ErrBlockListed                = errors.New("certificate is in the block list")
	ErrFingerprintMismatch        = errors.New("certificate fingerprint did not match")
	ErrSignatureMismatch          = errors.New("certificate signature did not match")
	ErrInvalidPublicKey           = errors.New("invalid public key")
	ErrInvalidPrivateKey          = errors.New("invalid private key")
	ErrPublicPrivateCurveMismatch = errors.New("public key does not match private key curve")
	ErrPublicPrivateKeyMismatch   = errors.New("public key and private key are not a pair")
	ErrPrivateKeyEncrypted        = errors.New("private key must be decrypted")
	ErrCaNotFound                 = errors.New("could not find ca for the certificate")
	ErrUnknownVersion             = errors.New("certificate version unrecognized")
	ErrCertPubkeyPresent          = errors.New("certificate has unexpected pubkey present")
	ErrCurveMismatch              = errors.New("certificate curve does not match CA")

	ErrInvalidPEMBlock                   = errors.New("input did not contain a valid PEM encoded block")
	ErrInvalidPEMCertificateBanner       = errors.New("bytes did not contain a proper certificate banner")
	ErrInvalidPEMX25519PublicKeyBanner   = errors.New("bytes did not contain a proper X25519 public key banner")
	ErrInvalidPEMX25519PrivateKeyBanner  = errors.New("bytes did not contain a proper X25519 private key banner")
	ErrInvalidPEMEd25519PublicKeyBanner  = errors.New("bytes did not contain a proper Ed25519 public key banner")
	ErrInvalidPEMEd25519PrivateKeyBanner = errors.New("bytes did not contain a proper Ed25519 private key banner")

	ErrNoPeerStaticKey = errors.New("no peer static key was present")

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Ensure node certs are signed by the same CA whose cert is in the pool — regenerate the node cert with the current ca.key/ca.crt.
  2. Verify file integrity (re-copy ca.crt and node.crt, compare checksums).
  3. Confirm the pool used at verification is the same CA environment that issued the cert.
  4. In tests, use the matching test CA fixture for the certificate under test.

Example fix

// before
// ca.crt from CA-A, node.crt signed by CA-B
pool := cert.NewCAPoolFromBytes(caA)
err := pool.VerifyCertificate(nodeB) // ErrSignatureMismatch

// after
pool := cert.NewCAPoolFromBytes(caB) // CA that actually signed nodeB
err = pool.VerifyCertificate(nodeB)
Defensive patterns

Strategy: try-catch

Validate before calling

if !c.CheckSignature(ca.Certificate.PublicKey()) {
    return fmt.Errorf("cert %s was not signed by the loaded CA", c.Name())
}

Type guard

func signedByCA(c cert.Certificate, ca cert.Certificate) bool {
    return c.CheckSignature(ca.Certificate.PublicKey())
}

Try / catch

if _, err := pool.VerifyCertificate(c, "", ""); errors.Is(err, cert.ErrSignatureMismatch) {
    return fmt.Errorf("cert/CA mismatch: re-sign the host cert with the deployed ca.crt")
}

Prevention

When it happens

Trigger: pool.verify: c.CheckSignature(signer.Certificate.PublicKey()) returns false (cert/ca_pool.go:241). Also produced by the nebula-cert CLI verify subcommand when the checked cert/signature pair doesn't match.

Common situations: ca.crt and node.crt generated from different CAs (mixing environments); the certificate file was edited/corrupted in transit; re-signed cert distributed with the old CA file; mismatched v1/v2 handling.

Understand the failure class

Related errors


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