{"record":{"id":"873cd15d0413f899","repo":"slackhq/nebula","slug":"errsignaturemismatch","errorCode":"ErrSignatureMismatch","errorMessage":"certificate signature did not match","messagePattern":"certificate signature did not match","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cert/errors.go","lineNumber":16,"sourceCode":"package cert\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar (\n\tErrBadFormat                  = errors.New(\"bad wire format\")\n\tErrRootExpired                = errors.New(\"root certificate is expired\")\n\tErrExpired                    = errors.New(\"certificate is expired\")\n\tErrNotCA                      = errors.New(\"certificate is not a CA\")\n\tErrNotSelfSigned              = errors.New(\"certificate is not self-signed\")\n\tErrBlockListed                = errors.New(\"certificate is in the block list\")\n\tErrFingerprintMismatch        = errors.New(\"certificate fingerprint did not match\")\n\tErrSignatureMismatch          = errors.New(\"certificate signature did not match\")\n\tErrInvalidPublicKey           = errors.New(\"invalid public key\")\n\tErrInvalidPrivateKey          = errors.New(\"invalid private key\")\n\tErrPublicPrivateCurveMismatch = errors.New(\"public key does not match private key curve\")\n\tErrPublicPrivateKeyMismatch   = errors.New(\"public key and private key are not a pair\")\n\tErrPrivateKeyEncrypted        = errors.New(\"private key must be decrypted\")\n\tErrCaNotFound                 = errors.New(\"could not find ca for the certificate\")\n\tErrUnknownVersion             = errors.New(\"certificate version unrecognized\")\n\tErrCertPubkeyPresent          = errors.New(\"certificate has unexpected pubkey present\")\n\tErrCurveMismatch              = errors.New(\"certificate curve does not match CA\")\n\n\tErrInvalidPEMBlock                   = errors.New(\"input did not contain a valid PEM encoded block\")\n\tErrInvalidPEMCertificateBanner       = errors.New(\"bytes did not contain a proper certificate banner\")\n\tErrInvalidPEMX25519PublicKeyBanner   = errors.New(\"bytes did not contain a proper X25519 public key banner\")\n\tErrInvalidPEMX25519PrivateKeyBanner  = errors.New(\"bytes did not contain a proper X25519 private key banner\")\n\tErrInvalidPEMEd25519PublicKeyBanner  = errors.New(\"bytes did not contain a proper Ed25519 public key banner\")\n\tErrInvalidPEMEd25519PrivateKeyBanner = errors.New(\"bytes did not contain a proper Ed25519 private key banner\")\n\n\tErrNoPeerStaticKey = errors.New(\"no peer static key was present\")","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/errors.go#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Verify file integrity (re-copy ca.crt and node.crt, compare checksums).","Confirm the pool used at verification is the same CA environment that issued the cert.","In tests, use the matching test CA fixture for the certificate under test."],"exampleFix":"// before\n// ca.crt from CA-A, node.crt signed by CA-B\npool := cert.NewCAPoolFromBytes(caA)\nerr := pool.VerifyCertificate(nodeB) // ErrSignatureMismatch\n\n// after\npool := cert.NewCAPoolFromBytes(caB) // CA that actually signed nodeB\nerr = pool.VerifyCertificate(nodeB)","handlingStrategy":"try-catch","validationCode":"if !c.CheckSignature(ca.Certificate.PublicKey()) {\n    return fmt.Errorf(\"cert %s was not signed by the loaded CA\", c.Name())\n}","typeGuard":"func signedByCA(c cert.Certificate, ca cert.Certificate) bool {\n    return c.CheckSignature(ca.Certificate.PublicKey())\n}","tryCatchPattern":"if _, err := pool.VerifyCertificate(c, \"\", \"\"); errors.Is(err, cert.ErrSignatureMismatch) {\n    return fmt.Errorf(\"cert/CA mismatch: re-sign the host cert with the deployed ca.crt\")\n}","preventionTips":["Sign and distribute node certs from the same CA environment used at runtime.","Checksum-verify ca.crt and host.crt when deploying.","Keep one CA per environment and label cert files accordingly."],"tags":["certificate","signature","trust-chain"],"backgroundTag":"signature-verification-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}