{"record":{"id":"c13852de770b3e0d","repo":"slackhq/nebula","slug":"could-not-calculate-fingerprint-to-verify-w","errorCode":null,"errorMessage":"could not calculate fingerprint to verify: %w","messagePattern":"could not calculate fingerprint to verify: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/ca_pool.go","lineNumber":163,"sourceCode":"// Returns true if the fingerprint is blocked.\nfunc (ncp *CAPool) IsBlocklisted(fingerprint string) bool {\n\tif _, ok := ncp.certBlocklist[fingerprint]; ok {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// VerifyCertificate verifies the certificate is valid and is signed by a trusted CA in the pool.\n// If the certificate is valid then the returned CachedCertificate can be used in subsequent verification attempts\n// to increase performance.\nfunc (ncp *CAPool) VerifyCertificate(now time.Time, c Certificate) (*CachedCertificate, error) {\n\tif c == nil {\n\t\treturn nil, fmt.Errorf(\"no certificate\")\n\t}\n\tfp, err := c.Fingerprint()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not calculate fingerprint to verify: %w\", err)\n\t}\n\n\tsigner, err := ncp.verify(c, now, fp, \"\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Pre nebula v1.10.3 could generate signatures in either high or low s form and validation\n\t// of signatures allowed for either. Nebula v1.10.3 and beyond clamps signature generation to low-s form\n\t// but validation still allows for either. Since a change in the signature bytes affects the fingerprint, we\n\t// need to test both forms until such a time comes that we enforce low-s form on signature validation.\n\tfp2, err := CalculateAlternateFingerprint(c)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not calculate alternate fingerprint to verify: %w\", err)\n\t}\n\tif fp2 != \"\" && ncp.IsBlocklisted(fp2) {\n\t\treturn nil, ErrBlockListed\n\t}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/ca_pool.go#L145-L181","documentation":"CAPool.VerifyCertificate computes the certificate's fingerprint before chain verification; if c.Fingerprint() fails, it returns 'could not calculate fingerprint to verify' wrapping the underlying error. The fingerprint is needed to look up the signer CA and cached certificates, so failures abort verification.","triggerScenarios":"Calling VerifyCertificate with a Certificate whose Fingerprint() returns an error — corrupted raw bytes, incomplete deserialization, or a broken custom Certificate implementation.","commonSituations":"Certificates decoded from damaged or truncated data on the wire, custom Certificate interface implementations with faulty Fingerprint methods, or memory/state corruption between decode and verify.","solutions":["Inspect the wrapped error to find the root cause of the fingerprint failure","Re-request or re-decode the peer certificate from a trusted source","Validate the certificate decodes cleanly (e.g. round-trip the PEM) before verifying","Fix custom Certificate implementations so Fingerprint has access to valid raw bytes"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check fingerprint health before verification\nif _, err := c.Fingerprint(); err != nil {\n    return fmt.Errorf(\"peer certificate unusable, skipping verify: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"cc, err := pool.VerifyCertificate(now, c)\nif err != nil {\n    if strings.Contains(err.Error(), \"could not calculate fingerprint to verify\") {\n        log.Warnf(\"dropping peer cert with broken fingerprint: %v\", err)\n        return err\n    }\n    return err\n}","preventionTips":["Decode peer certificates fully and check for errors before verification","Keep the raw certificate bytes intact between decode and verify (no partial copies)","Add unit tests for any custom Certificate implementation's Fingerprint method"],"tags":["certificate","fingerprint","verification","ca-pool"],"backgroundTag":"fingerprint-calculation-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"}